EntityFrameworkCore.Jet icon indicating copy to clipboard operation
EntityFrameworkCore.Jet copied to clipboard

OleDbException when HasColumnName is not specified

Open xoniuqe opened this issue 4 years ago • 1 comments

Hello my fellow developers! The good stuff at the beginning: I'm having a blast with the current alpha of this provider and my project is moving forward fast, also because of the fast reactions and fixes of all of you.

Today I stumbled over a strange behaviour: I was defining some entities via the fluent API and defined an owned entity for one of my classes.

I did it like so:

pBuilder.OwnsOne(o => o.AdvancedConfiguration, ac =>
            {
                ac.Property(p => p.ExecutionDateDeadline)./*HasColumnName("ExecutionDateDeadline").*/HasDefaultValueSql("15:30#");

If start the program with this configuration I get the following exception: System.Data.OleDb.OleDbException: 'Für mindestens einen erforderlichen Parameter wurde kein Wert angegeben.'

If I add the uncommented part with the HasColumnName everything works as I would expect it.

This not a huge deal because I can just use this function, but it seems like a bug in general.

xoniuqe avatar Jan 14 '21 13:01 xoniuqe

Generally, you code should work, after fixing the HasDefaultValueSql("15:30#"); syntax error (#15:30# is correct). I tested this using the following code:

Program.cs
using System;
using System.Diagnostics;
using System.Linq;
using EntityFrameworkCore.Jet.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace IssueConsoleTemplate
{
    public class Cookie
    {
        public int CookieId { get; set; }
        public string Name { get; set; }
        public BakingInformation BakingInformation { get; set; }
    }

    public class BakingInformation
    {
        public int CookieId { get; set; }
        public int DoughWeight { get; set; }
        public DateTime BakingTime { get; set; }
    }

    public class Context : DbContext
    {
        public DbSet<Cookie> Cookies { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseJetOleDb("Data Source=Issue96.accdb")
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Cookie>(
                entity =>
                {
                    entity.OwnsOne(
                        e => e.BakingInformation,
                        bi => bi.Property(p => p.BakingTime).HasDefaultValueSql("#15:30#"));
                });
        }
    }

    internal class Program
    {
        private static void Main()
        {
            using (var context = new Context())
            {
                context.Database.EnsureDeleted();
                context.Database.EnsureCreated();
                
                context.Cookies.AddRange(
                    new Cookie
                    {
                        Name = "Basic",
                        BakingInformation = new BakingInformation
                        {
                            DoughWeight = 35,
                        }
                    },
                    new Cookie
                    {
                        Name = "Chocolate Chip",
                        BakingInformation = new BakingInformation
                        {
                            DoughWeight = 40,
                            BakingTime = JetConfiguration.TimeSpanOffset.AddMinutes(20)
                        }
                    }
                );

                context.SaveChanges();
            }

            using (var context = new Context())
            {
                var cookies = context.Cookies
                    .OrderBy(e => e.CookieId)
                    .ToList();

                Trace.Assert(cookies.Count == 2);
                Trace.Assert(cookies[0].CookieId == 1);
                Trace.Assert(cookies[0].BakingInformation != null);
                Trace.Assert(cookies[0].BakingInformation.DoughWeight == 35);
                Trace.Assert(cookies[0].BakingInformation.BakingTime == JetConfiguration.TimeSpanOffset.AddHours(15).AddMinutes(30));
            }
        }
    }
}

It runs successfully and generates the following output:

EF Core Output
warn: Microsoft.EntityFrameworkCore.Model.Validation[10400]
      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data, this mode should only be enabled during development.

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 3.1.10 initialized 'Context' using provider 'EntityFrameworkCore.Jet' with options: DataAccessProviderFactory SensitiveDataLoggingEnabled DetailedErrorsEnabled

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (5,689ms) [Parameters=[], CommandType='Text', CommandTimeout='60']
      CREATE DATABASE 'Issue96.accdb';

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (18ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      CREATE TABLE `Cookies` (
          `CookieId` counter NOT NULL,
          `Name` longchar NULL,
          `BakingInformation_DoughWeight` integer NULL,
          `BakingInformation_BakingTime` datetime NULL DEFAULT #15:30#,
          CONSTRAINT `PK_Cookies` PRIMARY KEY (`CookieId`)
      );

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (94ms) [Parameters=[@p0='Basic' (Size = 255), @p1='35'], CommandType='Text', CommandTimeout='30']
      INSERT INTO `Cookies` (`Name`, `BakingInformation_DoughWeight`)
      VALUES (@p0, @p1);
      SELECT `CookieId`, `BakingInformation_BakingTime`
      FROM `Cookies`
      WHERE @@ROWCOUNT = 1 AND `CookieId` = @@identity;

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (5ms) [Parameters=[@p0='Chocolate Chip' (Size = 255), @p1='1899-12-30T00:20:00' (DbType = DateTime), @p2='40'], CommandType='Text', CommandTimeout='30']
      INSERT INTO `Cookies` (`Name`, `BakingInformation_BakingTime`, `BakingInformation_DoughWeight`)
      VALUES (@p0, @p1, @p2);
      SELECT `CookieId`
      FROM `Cookies`
      WHERE @@ROWCOUNT = 1 AND `CookieId` = @@identity;

info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
      Entity Framework Core 3.1.10 initialized 'Context' using provider 'EntityFrameworkCore.Jet' with options: DataAccessProviderFactory SensitiveDataLoggingEnabled DetailedErrorsEnabled

info: Microsoft.EntityFrameworkCore.Database.Command[20101]
      Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      SELECT `c`.`CookieId`, `c`.`Name`, `t`.`CookieId`, `t`.`BakingInformation_BakingTime`, `t`.`BakingInformation_DoughWeight`
      FROM `Cookies` AS `c`
      LEFT JOIN (
          SELECT `c0`.`CookieId`, `c0`.`BakingInformation_BakingTime`, `c0`.`BakingInformation_DoughWeight`
          FROM `Cookies` AS `c0`
          WHERE `c0`.`BakingInformation_DoughWeight` IS NOT NULL AND `c0`.`BakingInformation_BakingTime` IS NOT NULL
      ) AS `t` ON `c`.`CookieId` = `t`.`CookieId`
      ORDER BY `c`.`CookieId`

However, while testing the code, I came across an issue, where a single command containing multiple SQL statements (separated by ; characters), could lead to incorrectly assigned parameters (or missing parameters), when being split in to multiple commands. This has been fixed in #97.

I therefore suggest to fix the syntax error and then give it another try, If it still fails, use the latest daily build and try again.

lauxjpn avatar Jan 15 '21 03:01 lauxjpn