Entity Framework 带外键oracle 新增外键记录该怎么弄

博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)30442人阅读
与Entity Framework相伴的日子痛并快乐着。今天和大家分享一下一个快乐,两个痛苦。
先说快乐的吧。Entity Framework在将数据插入数据库时,如果主键字段是自增标识列,会将该自增值返回给实体对象对应的属性。
比如下面添加博客随笔至数据库的示例代码:
var blogPost = new BlogPost(){
Author = "博客园",
Title = "程序员的网上家园"};using (BlogDbContext context = new BlogDbContext()){
context.BlogPosts.Add(blogPost);
context.SaveChanges();return blogPost.ID;}
SaveChanges()之后,blogPost.ID的值就是数据库中对应自增标识列的值。
看一下Entity Framework生成的SQL语句:
exec sp_executesql N'insert [dbo].[blog_Content]([Title],[Author])values (@0, @1)select [ID]from [dbo].[blog_Content]where @@ROWCOUNT & 0 and [ID] = scope_identity()',N'@0 nvarchar(128),@1 nvarchar(128),',@0=N'程序员的网上家园',@1=N'博客园'
EF通过scope_identity()获取自增列的值,而且我们没有对BlogPost的ID属性进行任何设置,是EF智能地判断出ID就是自增标识列。
在以前没有使用Entity Framework的时代,用的是存储过程,存储过程有一堆参数,实体对象的属性值要一一对应地赋值给这些参数,执行存储过程之后,还要通过ParameterDirection.Output的参数获取自增ID的值。
现在,只要把东西交给Entity Framework,并和她说,把它放到数据库中去。多省心!多快乐!
但是,自以为是的Entity Framework用这个特性给人快乐的同时,也给人带来了一点痛苦。她认为只要实体类中有ID属性,数据库对应的是一定是自增标识列,真是够自以为是的。当我们把博客随笔添加至数据库后,准备用这个自增ID将随笔内容添加至数据库(随笔内容存储在单独的数据库,通过ID字段与随笔进行关联,不是自增的),却出现错误提示:
Cannot insert the value NULL into column 'ID', table 'CNBlogsText.dbo.blog_PostBody'; column does not allow nulls.
看看EF生成的SQL语句:
exec sp_executesql N'insert [dbo].[CNBlogsText_blog_PostBody]([Text])values (@0)select [ID]from [dbo].[CNBlogsText_blog_PostBody]where @@ROWCOUNT & 0 and [ID] = scope_identity()',N'@0 nvarchar(128)',@0=N'帮助程序员用技术改变世界'
不是自增列,也来个scope_identity()。这么聪明的Entity Framework,也会干这样的傻事。
还好,EF定制灵活的特性可以让我们轻松化解这个痛苦,只要在BlogDbContext中添加下面的代码:
protected override void OnModelCreating(DbModelBuilder modelBuilder){
modelBuilder.Entity&PostBody&().Property(p =& p.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); }
也可以通过在实体类属性上加标记实现:
public class BlogPost{
[DatabaseGenerated(DatabaseGeneratedOption.None)]public int ID { get; set; }}
第二个痛苦是众所周知的Entity Framework不支持枚举类型,虽然大家都知道,但还是想拿出晒晒,解解恨。
EF怎么对待枚举类型的呢?对于实体类中实实在在存在的枚举类型的属性,EF对它们视而不见,就当它不存在。
对于这个痛苦,目前无法化解(要等EF的下一版本),只能借助旁边左道减轻痛苦,请看“旁边左道”之“移花接木”。
实体类中的代码:
public class BlogPost{public BlogPostType PostType
{get { return (BlogPostType)PostTypeEf; }set { PostTypeEf = (int) }
}public int PostTypeEf { get; set; }}
EF不认枚举类型,但认int类型,所以增加个PostTypeEf,仅供EF专用,等EF的下一版本支持枚举类型时再去掉。
BlogDbContext也要博主最新文章
博主热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)我的个人网站:,欢迎大家光临!
我们在使用Entity Framework框架进行CRUD时,经常会出现各种各样的错误,下面请看我的实验结果。
以下是只用一个上下文对象进行操作:
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.Single(t =& t.Id == 2);
post.AuthorId = 1;
blog.SaveChanges();
结果:成功
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.Single(t =& t.Id == 2);
post.Author = blog.Authors.Single(t =& t.Id == 3);
blog.SaveChanges();
结果:成功
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.Single(t =& t.Id == 2);
post.AuthorId = 1;
post.Author = blog.Authors.Single(t =& t.Id == 4);
blog.SaveChanges();
结果:失败,报错如下:
Conflicting changes to the role 'Post_Author_Target' of the relationship 'ConsoleApplication1.DDD.Infrastructure.Post_Author' have been detected.
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.Single(t =& t.Id == 2);
post.Author = new Author() { Id = 4 };
blog.Entry(post.Author).State = EntityState.U
blog.SaveChanges();
结果:成功
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.Single(t =& t.Id == 2);
//author = new Author() { Id = 1, Name = "zwj" };//直接实例化或下面查询得出
author = blog.Authors.AsNoTracking().Single(t =& t.Id == 3);
post.Author =
blog.SaveChanges();
结果:成功,但是Authors表中会新增一笔记录,并将新的ID赋值给Posts表;原因:Author与Post不在同一个上下文中,Post所在的上下文中追踪不到Author的信息,故当成新增。
以下是在两个不同的上下文中进行操作:
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.AsNoTracking().Single(t =& t.Id == 2);
//blog.Entry(post).State = EntityState.D上面的AsNoTracking可以由这句实现
BlogDbContext blog2 = new BlogDbContext();
post.AuthorId = 5;
blog2.Entry(post).State = EntityState.M
blog2.SaveChanges();
结果:成功
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.AsNoTracking().Single(t =& t.Id == 2);
BlogDbContext blog2 = new BlogDbContext();
post.Author = blog2.Authors.Single(t =& t.Id == 5);
blog2.Entry(post).State = EntityState.M
blog2.SaveChanges();
结果:失败,报错如下:
A referential integrity constraint violation occurred: The property value(s) of 'Author.Id' on one end of a relationship do not match the property value(s) of 'Post.AuthorId' on the other end.
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.AsNoTracking().Single(t =& t.Id == 2);
BlogDbContext blog2 = new BlogDbContext();
author = blog2.Authors.AsNoTracking().Single(t =& t.Id == 1);
post.Author =
blog2.Entry(post).State = EntityState.M
blog2.SaveChanges();
结果:失败,报错同第七次
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.AsNoTracking().Single(t =& t.Id == 2);
author = blog.Authors.AsNoTracking().Single(t =& t.Id == 3);
BlogDbContext blog2 = new BlogDbContext();
post.Author =
blog2.Entry(post).State = EntityState.M
blog2.SaveChanges();
结果:失败,报错同第七次
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.AsNoTracking().Single(t =& t.Id == 2);
BlogDbContext blog2 = new BlogDbContext();
author = new Author() { Id = 1, Name = "zwj" };
post.Author =
blog2.Entry(post).State = EntityState.M
blog2.SaveChanges();
结果:失败,报错同第七次
第十一次:
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.AsNoTracking().Single(t =& t.Id == 2);
BlogDbContext blog2 = new BlogDbContext();
author = blog2.Authors.Single(t =& t.Id == 1);
post.Author =
post.AuthorId = author.Id;
blog2.Entry(post).State = EntityState.M
blog2.SaveChanges();
结果:成功,但我认为主要是通过赋值AuthorId来完成的,与第六次相同,去掉赋值AuthorId,则与第七次相同的报错
第十二次:
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.AsNoTracking().Single(t =& t.Id == 2);
BlogDbContext blog2 = new BlogDbContext();
author = blog2.Authors.Single(t =& t.Id == 3);
blog2.Entry(post).Reference(t =& t.Author).CurrentValue =
blog2.Entry(post).State = EntityState.M
blog2.SaveChanges();
结果:失败,报错同第七次
第十三次:
BlogDbContext blog = new BlogDbContext();
post = blog.Posts.AsNoTracking().Single(t =& t.Id == 2);
BlogDbContext blog2 = new BlogDbContext();
blog2.Posts.Attach(post);
post.Author = blog2.Authors.Single(t =& t.Id == 1);
blog2.SaveChanges();
结果:成功
最后得出结论:
1.在同一个上下文中,不论是采用直接赋值导航属性或是直接赋值外键属性,除不能同时对导航属性及外键属性赋不相关联的值外,都可以成功;
2.不在同一个上下文中,若想在完成CUD时,则必需先确保要进行操作的实体处于Detached状态,然后再进行相应的更新,涉及导航属性时,只能采用赋值外键属性,不能通过导航属性直接赋值,否则会报错(这个我觉得是个BUG,不知大家有什么好的解决办法没有),若采用先在新的上下文中Attached,再进行更新操作则与第1条结论相同。
阅读(...) 评论()Entity Framework Code First添加修改及删除外键关联实体_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Entity Framework Code First添加修改及删除外键关联实体
阅读已结束,下载本文需要
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,同时保存到云知识,更方便管理
加入VIP
还剩3页未读,
定制HR最喜欢的简历
你可能喜欢}

我要回帖

更多关于 新增外键 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信