C# DbContext正在尝试将非null字段保存为null

C# DbContext正在尝试将非null字段保存为null,c#,sql-server,entity-framework-core,C#,Sql Server,Entity Framework Core,我有两个项目 StoreSku.Data - Depends On: Microsoft.EntityFrameworkCore StoreSku.Provider - Depends On: StoreSku.Data, Microsoft.EntityFrameworkCore.SqlServer 我不想将StoreSku.Data绑定到任何特定的提供者,因此我已将该职责转移到StoreSku.provider。我正在StoreSku.Provider中创建模型和选项,并使用以下代码将选项

我有两个项目

StoreSku.Data - Depends On: Microsoft.EntityFrameworkCore
StoreSku.Provider - Depends On: StoreSku.Data, Microsoft.EntityFrameworkCore.SqlServer
我不想将
StoreSku.Data
绑定到任何特定的提供者,因此我已将该职责转移到
StoreSku.provider
。我正在
StoreSku.Provider
中创建模型和选项,并使用以下代码将选项传递到
DbContext

var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(connectionString);

var conventions = new ConventionSet();
var modelBuilder = new ModelBuilder(conventions);

modelBuilder.Entity<StoreSkuUpdateRequest>().HasKey(request => request.Id);
modelBuilder.Entity<StoreSkuUpdateRequest>().Property(request => request.Id).UseSqlServerIdentityColumn();
modelBuilder.Entity<StoreSkuUpdateRequest>().Property(request => request.StoreNumber).ValueGeneratedNever();
modelBuilder.Entity<StoreSkuUpdateRequest>().Property(request => request.BusinessDate).ValueGeneratedNever();
modelBuilder.Entity<StoreSkuUpdateRequest>().Property(request => request.Timestamp).ValueGeneratedNever();
modelBuilder.Entity<StoreSkuUpdateRequest>().HasMany(request => request.RequestedUpdates).WithOne(update => update.UpdateRequest);
modelBuilder.Entity<StoreSkuUpdateRequest>().HasMany(request => request.RelatedUpdates).WithOne(relatedUpdate => relatedUpdate.UpdateRequest);
modelBuilder.Entity<StoreSkuUpdateRequest>().ForSqlServerToTable("StoreSkuUpdateRequest");

modelBuilder.Entity<StoreSkuAvailabilityUpdate>().HasOne(update => update.UpdateRequest).WithMany(request => request.RequestedUpdates);
modelBuilder.Entity<StoreSkuAvailabilityUpdate>().HasMany(update => update.RelatedUpdates).WithOne(relatedUpdate => relatedUpdate.RequestedUpdate);
modelBuilder.Entity<StoreSkuAvailabilityUpdate>().ForSqlServerToTable("RequestedStoreSkuUpdate");

modelBuilder.Entity<RelatedStoreSkuUpdate>().HasOne(relatedUpdate => relatedUpdate.RequestedUpdate).WithMany(update => update.RelatedUpdates);
modelBuilder.Entity<RelatedStoreSkuUpdate>().HasOne(relatedUpdate => relatedUpdate.UpdateRequest).WithMany(request => request.RelatedUpdates);
modelBuilder.Entity<RelatedStoreSkuUpdate>().ForSqlServerToTable("RelatedStoreSkuUpdate");

optionsBuilder.UseModel(modelBuilder.Model);

DbContextOptions options = optionsBuilder.Options;
此表的架构是

CREATE TABLE [dbo].[StoreSkuUpdateRequest](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[StoreNumber] [int] NOT NULL,
[BusinessDate] [date] NOT NULL,
[Timestamp] [datetime] NOT NULL)
模型呢

public sealed class StoreSkuUpdateRequest
{
    [Required]
    public long Id { get; set; }

    [Required]
    public int StoreNumber { get; set; }

    [Required]
    public DateTime BusinessDate { get; set; }

    [Required]
    public DateTime Timestamp { get; set; }
}
以及呼叫代码:

using (Context)
{
    var request = new StoreSkuUpdateRequest
    {
        StoreNumber = 12345,
        BusinessDate = DateTime.UtcNow,
        Timestamp = DateTime.UtcNow
    };
    Context.StoreSkuAvailabilityUpdateRequests.Add(request);

    Context.SaveChanges();
}
正在生成的SQL命令是

BEGIN TRANSACTION

SET NOCOUNT ON;
INSERT INTO [StoreSkuUpdateRequest]
DEFAULT VALUES;
SELECT [Id]
FROM [StoreSkuUpdateRequest]
WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();

ROLLBACK TRANSACTION 

为什么我必须指定
ValueGeneratedNever()?为什么EFCore试图将它们保存为
null

在triage中讨论并决定我们应该有ModelBuilder工厂,这样人们就不必担心约定等问题(特别是因为约定对于第一个版本来说是“内部的”)

人们可以像这样创建一个工厂(注意,这是工厂上的一个静态create()方法,而不是一个默认的ctor来获取工厂,因为使用默认的ctor不适合DI):

var builder=SqlServerModelBuilderFactory.Create()

或者,如果您希望它从DI获得所有服务,那么我们将注册一个您可以解决的服务。。。然后,您将获得在DI中注册的相同记录器等(另外,如果您已经覆盖了类型映射器等,那么您还将获得这些服务)

sp.AddEntityFramework()
.AddSqlCompact()
.AddNpgSql()
.AddSqlServer()

var builder=sp.GetService().Create()

我无法找到
SqlServerModelBuilderFactory
类,这导致我调查是否存在
SqlServerConventionSetBuilder
;有

所以从

var conventions = new ConventionSet();


立即修复了我。

StoreSkuUpdateRequest和StoreSkuAvailabilityUpdate之间的关系是什么?我有点困惑,你是在创建一个UpdateRequest,然后将它添加到AvailabilityUpdateRequests?两者之间似乎存在关系(历史),但如果这归结为EF必须解决的FK关系,则可能是执行类似插入+更新场景的操作。请使用SQL探查器进行检查,以查看SaveChanges上发送到DB的确切内容。问题的核心原因是使用空的
约定集创建的
ModelBuilder
,当传递给正常的
OnModelCreating
ModelBuilder
被初始化为包含所有EF核心约定的
ConventionSet
。@IvanStoev我想可能是这样,但我找不到任何类型的
AllConventionsSet
,所有的实现都记录为
,该API支持实体框架核心基础设施,不打算直接从代码中使用。此API可能会在将来的版本中更改或删除
BEGIN TRANSACTION

SET NOCOUNT ON;
INSERT INTO [StoreSkuUpdateRequest]
DEFAULT VALUES;
SELECT [Id]
FROM [StoreSkuUpdateRequest]
WHERE @@ROWCOUNT = 1 AND [Id] = scope_identity();

ROLLBACK TRANSACTION 
var conventions = new ConventionSet();
var conventions = SqlServerConventionSetBuilder.Build();