使用代理

为 POCO 实体类型创建实例时,实体框架常常为充当实体代理的动态生成的派生类型创建实例。此代理重写实体的某些虚拟属性,这样可在访问属性时插入挂钩,从而自动执行操作。例如,此机制用于支持关系的延迟加载。

禁止创建代理

有时需要禁止实体框架创建代理实例。例如,人们通常认为序列化非代理实例要比序列化代理实例容易得多。可通过清除 ProxyCreationEnabled 标记来关闭代理创建功能。上下文的构造函数便是可执行此操作的一个位置。例如:

public class  BloggingContext: DbContext

{

  publicBloggingContext()

  {

    this.Configuration.ProxyCreationEnabled=  false;

  }

 

  public DbSet<Blog>Blogs { get; set;}

  public DbSet<Post>Posts { get; set;}

}

请注意,在无需代理执行任何操作的情况下,EF 不会为类型创建代理。这意味着,也可以通过使用封装和/或没有虚拟属性的类型,避免生成代理。

添加新实体

使用DbSet.Add方法添加实体

using(var context = new BloggingContext())

{

  var blog = new Blog { Name = "ADO.NET Blog" };

  context.Blogs.Add(blog);

  context.SaveChanges();

}

修改Entry的State来添加实体

using(var context = new BloggingContext())

{

  var blog = new Blog { Name = "ADO.NET Blog" };

  context.Entry(blog).State =EntityState.Added;

  context.SaveChanges();

}

设置导航属性来添加实体

using(var context = new BloggingContext())

{

  // Add a new Userby setting a reference from a tracked Blog

  var blog =context.Blogs.Find(1);

  blog.Owner = newUser { UserName =  "johndoe1987" };

 

  // Add a new Postby adding to the collection of a tracked Blog

  var blog =context.Blogs.Find(2);

  blog.Posts.Add(newPost { Name = "Howto Add Entities" });

 

  context.SaveChanges();

}

所有被添加到上下文中的实体的引用实体,如果没有被跟踪,就会被当作新实体添加到上下文中,并在调用SaveChanges方法后被保存到数据库。

附加实体到上下文

如果实体在数据库中存在,但是没有被上下文跟踪,可是使用DbSet.Attach方法将其附加到上下文,附加之后,实体处于Unchanged状态。处于Unchanged状态的实体不会参与SaveChanges的逻辑。

var existingBlog = new Blog{ BlogId = 1, Name =  "ADO.NET Blog"};

 

using(var context = new BloggingContext())

{

  context.Blogs.Attach(existingBlog);

 

  // Do some morework... 

 

  context.SaveChanges();

}
var existingBlog = new Blog {
    BlogId = 1,
    Name = "ADO.NET Blog"
};
using(var context = new BloggingContext()) {
    context.Blogs.Attach(existingBlog); // Do some morework...    context.SaveChanges();}

设置DbEntityEntry对象的State属性,也可以附加对象到上下文中,如下:

var existingBlog = new Blog{ BlogId = 1, Name =  "ADO.NET Blog"};

 

using(var context = new BloggingContext())

{

  context.Entry(existingBlog).State =EntityState.Unchanged;

 

  // Do some morework... 

 

  context.SaveChanges();

}

使用上述两种方法附加到上下文的实体如果还引用其他实体,那么这些实体也会被附加到上下文中,状态为Unchanged

使用如下方法附加一个存在于数据库,但是还没有附加到上下文的已修改实体:

var existingBlog = new Blog{ BlogId = 1, Name =  "ADO.NET Blog"};

 

using(var context = new BloggingContext())

{

  context.Entry(existingBlog).State =EntityState.Modified;

 

  // Do some morework... 

 

  context.SaveChanges();

}

如果把一个实体的状态置为Modified,那么该实体的所有属性都将被标记为已更改状态,当SaveChanges被调用时,所有的属性值都将被保存到数据库。如果不想保存所有值,可以单独为每个想要修改的属性设置IsModified属性,如下:

using(var context = new BloggingContext())

{

    var blog =context.Blogs.Find(1);

 

    context.Entry(blog).Property(u =>u.Name).IsModified =  true;

 

    // Use a stringfor the property name

    context.Entry(blog).Property("Name").IsModified = true;

}

如果该实体还引用其他未被跟踪实体,那么这些实体将会作为Unchanged状态的实体附加到上下文。如果想修改这些实体,只能单独把每个引用实体设置为修改状态。

乐观并发模式

在尝试保存使用外键关联的实体期间,如果检测到乐观并发异常,SaveChanges 将引发 DbUpdateConcurrencyException。DbUpdateConcurrencyException的 Entries 方法为无法更新的实体返回 DbEntityEntry 实例。

使用DbContext执行原始SQL

使用SqlQuery方法执行SQL查询

using(var context = new BloggingContext())

{

  var blogs =context.Blogs.SqlQuery("SELECT * FROMdbo.Blogs").ToList();

}

执行存储过程查询

using(var context = new BloggingContext())

{

  var blogs =context.Blogs.SqlQuery("dbo.GetBlogs").ToList();

}

为存储过程传递参数

using(var context = new BloggingContext())

{

  var blogId =1;

 

  var blogs =context.Blogs.SqlQuery("dbo.GetBlogById@p0", blogId).Single();

}

查询非实体类型

using(var context = new BloggingContext())

{

  var blogNames= context.Database.SqlQuery<string>(

                     "SELECTName FROM dbo.Blogs").ToList();

}

返回是的对象将不会被跟踪,即使返回类型是实体类型。

执行SQL命令

using(var context = new BloggingContext())
{

  context.Database.SqlCommand(

      "UPDATEdbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1");

}