我有一个简单的模型,带有“BaseEntity”和派生的“Fund”实体。 当我尝试插入新基金时:
HybridModelContainer container = new HybridModelContainer();
//Create new Fund
Fund fund = new Fund();
fund.Id = Guid.NewGuid();
fund.DateCreated = DateTime.Now;
fund.Name = "Fund 1";
fund.Number = 1;
container.BaseEntities.AddObject(fund);
container.SaveChanges();
我收到以下错误:
“无法将值NULL插入列'Id',表'HybridData.dbo.BaseEntities';列不允许空值.INSERT失败。
声明已经终止。“
似乎分配给基金实体的ID未插入BaseEntity表。为什么不?
我做了这个“模特第一”。如果我先设计数据库,并从中创建模型,一切正常......但我需要先建立模型!
另外......为什么我的ObjectSet
中没有“Funds
”DataContext
(即container.Funds
)?在此先感谢您的帮助!
答案 0 :(得分:8)
我只能回答你问题的第二部分:“另外......为什么我的DataContext中没有”基金“的ObjectSet(即container.Funds)?”
ObjectContext在类层次结构中只有一个基类的ObjectSet是正常的。实际上并不需要派生类的ObjectSet。要在ObjectContext中添加和删除派生对象,您可以像在示例中一样使用AddObject
/ DeleteObject
的{{1}}和ObjectSet<BaseEntity>
方法。 / p>
对于查询派生对象,您可以利用ObjectSet的BaseEntities
方法。它返回派生类型的ObjectQuery,您可以在其中构建进一步的查询:
OfType
(问题的第一部分听起来像存储和概念模型之间的映射错误。它可能有更好的cif,你可以显示你的edmx文件的相关部分。)
编辑:问题第一部分的可能解决方案:
我已经在VS2010中使用Model-first创建了您的示例,我可以重现您的问题。问题似乎与模型中的主键不是ObjectQuery<Fund> query = container.BaseEntities.OfType<Fund>();
而是Int32
这一事实有关。当您向模型中添加新实体时,设计人员始终建议将Guid
作为主键,并将Int32
设置为StoreGeneratedPattern
。
如果您现在将模型设计器中的键类型从Identity
更改为Int32
,但保持Guid
不变为StoreGeneratedPattern
,则DDL会创建一个数据库将Identity
设置为Id
的SQL Server,但该列的标识规范为“否”。
因此,当EF向DB发送INSERT命令时,它会从模型定义中“思考”主数据库将在数据库中自动生成,并且不会将Guid发送到您在代码中分配的数据库。但是DB不会创建密钥,导致密钥为NULL值。因此我们得到的错误。
解决方案:在模型设计器中为uniqueidentifier
Id
到BaseEntity
的{{1}}属性设置。对我而言,它起作用了。当然,您有责任在向ObjectSet添加新对象之前始终将Guid分配给StoreGeneratedPattern
,但这似乎也是您想要的。