Gen*_*ick 5 many-to-many entity-framework insert entity-framework-4
这似乎应该是非常明显的,但实体框架的一些东西让我感到困惑,我无法让它工作.
很简单,我有三个表,Id值是标识列:Users(userId,username)Categories(categoryId,categoryName)JoinTable(UserId,CategoryId)composite.
在实体设计器(这是.net 4.0)中,当我导入这些表时,正如预期的那样,连接表不会出现,但用户和类别显示关系.以下代码:
var _context = new MyContext();
var myUser = new User();
myUser.UserName = "joe";
var myCategory = new Category();
myCategory.CategoryName = "friends";
_context.Users.AddObject(myUser);
myUser.Categories.Add(myCategory);
var saved = _context.SaveChanges();
Run Code Online (Sandbox Code Playgroud)
返回错误(尽管没有添加到数据库中):
An item with the same key has already been added.
Run Code Online (Sandbox Code Playgroud)
如果我在保存之前添加以下内容:
_context.Categories.AddObject(myCategory);
myCategory.Users.Add(myUser);
Run Code Online (Sandbox Code Playgroud)
我得到相同的错误,并没有保存到数据库.如果我在尝试关联它们之前保存myUser和myCategory对象,它们都会保存,但是第二次保存会抛出错误,而没有添加到连接表中:
Cannot insert the value NULL into column 'UserId', table '...dbo.JoinTable'; column does not allow nulls. INSERT fails. The statement has been terminated.
Run Code Online (Sandbox Code Playgroud)
我显然无法理解插入了多少个关系.我错过了什么?
在将User和Category实体添加到数据库之后,您需要调用SaveChanges(),然后设置它们之间的关联.
但是,这里的真正问题是您列出的第二个例外.如果您在调试器中查看SqlProfiler或ADO.NET探查器,您将看到在第二次SaveChanges调用期间它看起来像这样:
insert [dbo].[JoinTable]([UserId]) values (@0) select [CategoryId] from
[dbo].[JoinTable] where @@ROWCOUNT > 0 and [UserId] = @0 and [CategoryId] = scope_identity()
Run Code Online (Sandbox Code Playgroud)
显然,如果您正确编程了JoinTable(两列上的复合PK),这将不起作用.
如果我通过模型浏览器查看EntityModel存储,它会显示JoinTable中的CategoryId列确实将StoreGeneratedPattern设置为Identity,而UserId设置为None.为什么EF在复合PK存在的生成阶段这样做是超出我的.我将向MS发布有关此问题的错误,但同时您可以在生成后手动编辑edmx/ssdl文件以删除Identity说明符.在JoinTable的EntityType标记的Property标记下找到StoreGeneratedPattern ="Identity"字符串并将其删除:
更改:
<Property Name="CategoryId" Type="int" Nullable="false" StoreGeneratedPattern="Identity" />
Run Code Online (Sandbox Code Playgroud)
至:
<Property Name="CategoryId" Type="int" Nullable="false" />
Run Code Online (Sandbox Code Playgroud)
然后,当您运行代码时,您将获得更好的插入查询(并且没有更多例外!):
insert [dbo].[JoinTable]([UserId], [CategoryId]) values (@0, @1)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5944 次 |
| 最近记录: |