我有两个项目
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;
你可以看到,这相当冗长。我是否需要所有这些调用是另一个问题。我的问题更集中在以下方面:
modelBuilder.Entity<StoreSkuUpdateRequest>().Property(request => request.StoreNumber).ValueGeneratedNever();
modelBuilder.Entity<StoreSkuUpdateRequest>().Property(request => request.BusinessDate).ValueGeneratedNever();
modelBuilder.Entity<StoreSkuUpdateRequest>().Property(request => request.Timestamp).ValueGeneratedNever();
我遇到的错误是,如果我没有这些行,我会得到以下错误:
Cannot insert the value NULL into column 'StoreNumber', table 'dbo.StoreSkuUpdateRequest'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Cannot insert the value NULL into column 'BusinessDate', table 'dbo.StoreSkuUpdateRequest'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Cannot insert the value NULL into column 'Timestamp', table 'dbo.StoreSkuUpdateRequest'; column does not allow nulls. INSERT fails.
The statement has been terminated.
这个表的架构是
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?
ConventionSet
创建了ModelBuilder
,而正常的OnModelCreating
方法中传递的ModelBuilder
则是使用包含所有EF Core约定的ConventionSet
进行初始化的。 - Ivan StoevAllConventionsSet
,而且所有实现都被记录为此 API 支持 Entity Framework Core 基础结构,不应直接从您的代码中使用。此 API 可能会在未来的版本中更改或删除。
- Zymus