一. 基本数据

  每个EF上下文实例都有一个 ChangeTracker(更改跟踪器),它负责跟踪需要写入数据库的更改。 当更改实体类的实例时(修改属性,删除实例,新建实例等),这些更改会记录在 ChangeTracker 中,然后在调用 SaveChanges 时被写入数据库。 此数据库提供程序负责将更改,转换为特定的数据库操作(例如,关系数据库的 INSERTUPDATE 和 DELETE 命令)。

 

  1.1 添加数据 

    使用 DbSet.Add 方法添加实体类的新实例。 调用 SaveChanges 时,数据将插入到数据库中。

         var blog = new Blog { Url = "http://sample.com" };
context.Blogs.Add(blog);
context.SaveChanges();

  1.2 更新数据

    EF 将通过ChangeTracker自动检测上下文对现有实体所做的更改。 检测包括从数据库查询的实体,以及之前添加并保存到数据库的实体。例如下面示例,从数据库查询的实体,只需通过赋值来修改属性,然后调用 SaveChanges 即可

         var blog = context.Blogs.First();
blog.Url = "http://sample.com/blog";
context.SaveChanges();

  1.3 删除数据

    使用 DbSet.Remove 方法删除实体类的实例。

    (1)如果实体已存在于数据库中,则将在“SaveChanges”期间删除该实体,并且删除数据库中的数据。

    (2)如果实体尚未保存到数据库(即跟踪为“已添加”),则在调用SaveChanges时,该实体会从上下文中移除且不再插入。

           //第一种情况
var blog = context.Blogs.First();
context.Blogs.Remove(blog);
context.SaveChanges();
//第二种情况
Blog blog = new Blog() { Url = "www.baidu.com" };
//添加后该实体为已添加,尚未保存到数据库
BloggingContext.Blogs.Add(blog);
//删除实体类的实例
BloggingContext.Blogs.Remove(blog);
//从上下文中移除blog实体
BloggingContext.SaveChanges();

  1.4 单个 SaveChanges 中的多个操作

    可以将多个添加/更新/删除操作合并到对“SaveChanges”的单个调用。

        // add
  context.Blogs.Add(new Blog { Url = "http://sample.com/blog_one" });
   context.Blogs.Add(new Blog { Url = "http://sample.com/blog_two" });   // update
  var firstBlog = context.Blogs.First();
  firstBlog.Url = "";    // remove
  var lastBlog = context.Blogs.Last();
  context.Blogs.Remove(lastBlog);   context.SaveChanges();

二.关联数据

  除了上面对独立实体进行保存外,还可以保存模型中定义的关系(主体实体和依赖实体)

    

  1.1 添加关系数据

    如果创建多个新的依赖实体,在添加主体到上下文时,也会添加其他依赖实体。在下面的示例中,blog博客和三篇相关文章post将全部被插入数据库中。 由于可通过 Blog.Posts 导航属性访问这些文章,因此可发现并添加它们(Posts三条信息到数据库)。

    var blog = new Blog
{
Url = "http://blogs.msdn.com/dotnet",
Posts = new List<Post>
{
new Post { Title = "Intro to C#" },
new Post { Title = "Intro to VB.NET" },
new Post { Title = "Intro to F#" }
}
};
  
context.Blogs.Add(blog);
context.SaveChanges();

  

  1.2 添加相关实体

    如果从上下文跟踪的实体的导航属性中,引用新实体。将发现该新实体并将其插入到数据库中。在下面的示例中,会保存 post 实体,因为该实体会添加到已从数据库中提取的 blog 实体的 Posts 属性。

      var blog = context.Blogs.Include(b => b.Posts).First();
var post = new Post { Title = "Intro to EF Core" };
//引用新实体,
blog.Posts.Add(post);
context.SaveChanges();

  1.3 更改关系

    如果更改实体的导航属性,则将对数据库中的外键列进行相应的更改。在下面的示例中,post 依赖实体更新关系,关联新的 blog主体实体,新 blog 会插入到数据库中, post的导航属性引用的新实体blog。

      //新增一个主体实体
   var blog = new Blog { Url = "http://blogs.msdn.com/visualstudio" };
   var post = context.Posts.First();
   //post更新关系
   post.Blog = blog;    context.SaveChanges();

  1.4 删除关系

    在下面的示例中,对 Blog 和 Post 之间的关系配置了级联删除,因此将从数据库中删除 post 实体。         

      var blog = context.Blogs.Include(b => b.Posts).First();
   var post = blog.Posts.First();
   //删除一条post依赖实体
   blog.Posts.Remove(post);   context.SaveChanges();

三.联级删除 

  级联删除是指:允许在删除某行时,自动触发删除相关的行。 即依赖实体与主实体的关系已断开时,自动删除该子实体,这通常称为“删除孤立项”。

  

  3.1 实体删除示例

       var blog = context.Blogs.Include(b => b.Posts).First();
var posts = blog.Posts.ToList();
context.Remove(blog); context.SaveChanges();
  -- 解发SaveChanges后,删除主体时,先自动删除子实体(具有必选或可选关系的 DeleteBehavior.Cascade级联)
DELETE FROM [Posts] WHERE [PostId] = 1
DELETE FROM [Posts] WHERE [PostId] = 2
DELETE FROM [Blogs] WHERE [BlogId] = 1

    关于联级删除,涉及到的外键约束包括:可选关系(可以为 null 的外键) 和 必须关系(不可为 null 的外键),参考官网

四. 事务       

  事务是指:允许以原子方式处理多个数据库操作。 如果已提交事务,则所有操作都会成功应用到数据库。 如果已回滚事务,则所有操作都不会应用到数据库。关于数据事务的详细介绍可网上查看。

  4.1 默认事务行为(隐式事务)

    默认情况下,如果数据库提供程序支持事务,则会在事务中应用对 SaveChanges() 的单一调用中的所有更改。  这意味着SaveChanges() 可保证提交到数据库完全成功或在出现错误时全部回滚。

    下面来演示默认事务行为,建立blogs表的url字段唯一约束。

    --创建唯一索引
    CREATE UNIQUE INDEX IX_Url ON Blogs(Url)
       //修改数据
var blog = BloggingContext.Blogs.First();
blog.Title = ""; //插入数据,再次插入违反约束
BloggingContext.Blogs.Add(new Blog() { Url = "www.baidu.com" }); BloggingContext.SaveChanges();

    检查数据库,该表数据没有做任何更改,通过sql 监听如下所示:

  

  4.2  控制事务(显示事务)

    对于大多数应用程序,上面4.1 默认事务已足够。 如果应用程序要求被视为有必要,则应该仅手动控制事务。

    可以使用 DbContext.Database API 开始、提交和回滚事务。 以下示例显示了两个 SaveChanges() 操作以及正在单个事务中执行的 LINQ 查询。并非所有数据库提供程序都支持事务。 调用事务 API 时,某些提供程序可能会引发异常或不执行任何操作。

    using (var transaction = context.Database.BeginTransaction())
{
try
{
context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
context.SaveChanges(); context.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/visualstudio" });
context.SaveChanges(); var blogs = context.Blogs
.OrderBy(b => b.Url)
.ToList(); // Commit transaction if all commands succeed, transaction will auto-rollback when disposed if either commands fails
transaction.Commit();
}
catch (Exception)
{
// TODO: Handle failure
}
}

 

  4.3 跨上下文事务(仅限关系数据库)

    可以跨多个EF上下文实例,共享一个事务。 此功能仅在使用关系数据库提供程序时才可用,因为该提供程序需要使用特定于关系数据库的 DbTransaction 和 DbConnection

    (1) 允许在外部提供连接

      是指共享 DbConnection 时,需要在DbContext构造上下文时向其中传入连接的功能。最简单方式是停止使用默认的 DbContext.OnConfiguring 方法来配置上下文,在外部创建 DbContextOptions,然后将其传递到上下文构造函数。如下所示:

public class BloggingContext : DbContext
{
private DbConnection _connection; public BloggingContext(DbConnection connection)
{
_connection = connection;
} public DbSet<Blog> Blogs { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(_connection);
}
}

  (2)共享连接和跨上下文的事务

//创建共享连接
var options = new DbContextOptionsBuilder<BloggingContext>()
.UseSqlServer(new SqlConnection(connectionString))
.Options; using (var context1 = new BloggingContext(options))
{
using (var transaction = context1.Database.BeginTransaction())
{
try
{
context1.Blogs.Add(new Blog { Url = "http://blogs.msdn.com/dotnet" });
context1.SaveChanges(); using (var context2 = new BloggingContext(options))
{
context2.Database.UseTransaction(transaction.GetDbTransaction()); var blogs = context2.Blogs
.OrderBy(b => b.Url)
.ToList();
} // Commit transaction if all commands succeed, transaction will auto-rollback when disposed if either commands fails
transaction.Commit();
}
catch (Exception)
{
// TODO: Handle failure
}
}
}

    未完...

参考文献:

    保存数据

 

asp.net core系列 34 EF保存数据(1)的更多相关文章

  1. asp.net core系列 35 EF保存数据(2) -- EF系列结束

    一.事务 (1) 事务接着上篇继续讲完.如果使用了多种数据访问技术,来访问关系型数据库,则可能希望在这些不同技术所执行的操作之间共享事务.下面示例显示了如何在同一事务中执行 ADO.NET SqlCl ...

  2. asp.net core系列 32 EF查询数据 必备知识(1)

    一.查询的工作原理 Entity Framework Core 使用语言集成查询 (LINQ) 来查询数据库中的数据. 通过 LINQ 可使用 C#(或你选择的其他 .NET 语言)基于派生上下文和实 ...

  3. asp.net core系列 33 EF查询数据 (2)

    一. 原生SQL查询 接着上篇讲.通过 Entity Framework Core 可以在使用关系数据库时下降到原始 SQL 查询. 在无法使用 LINQ 表达要执行的查询时,或因使用 LINQ 查询 ...

  4. asp.net core系列 30 EF管理数据库架构--必备知识 迁移

    一.管理数据库架构概述 EF Core 提供两种主要方法来保持 EF Core 模型和数据库架构同步.一是以 EF Core 模型为基准,二是以数据库为基准. (1)如果希望以 EF Core 模型为 ...

  5. asp.net core系列 31 EF管理数据库架构--必备知识 反向工程

    一.   反向工程 反向工程是基于数据库架构,生成的实体类和DbContext类代码的过程,对于Visual Studio开发,建议使用PMC.对于其他开发环境,请选择.NET Core CLI工具( ...

  6. asp.net core 系列 22 EF(连接字符串,连接复原,DbContext)

    一.连接字符串 在上二篇中,ASP.NET Core 应用程序连接字符串是写死在ConfigureServices代码中,下面介绍通过配置来实现.连接字符串可以存储在 appsettings.json ...

  7. asp.net core 系列 21 EF现有数据库进行反向工程

    一.概述 在上篇中使用EF基于数据模型创建数据库,  本篇继续使用 EF  基于数据库创建数据模型.  实现对已有数据库进行反向工程,来构建数据访问的 ASP.NET Core MVC 应用程序.已有 ...

  8. asp.net core 系列 20 EF基于数据模型创建数据库

    一.概述 本章使用 Entity Framework Core 构建执行基本数据访问的 ASP.NET Core MVC 应用程序.使用迁移(migrations)基于数据模型创建数据库,是一种cod ...

  9. asp.net core系列 28 EF模型配置(字段,构造函数,拥有实体类型)

    一. 支持字段 EF允许读取或写入字段而不是一个属性.在使用实体类时,用面向对象的封装来限制或增强应用程序代码对数据访问的语义时,这可能很有用.无法使用数据注释配置.除了约定,还可以使用Fluent ...

随机推荐

  1. 类中被final修饰的成员变量需要初始化

    类中被final修饰的成员变量需要初始化,否则编译不通过,因为final修饰后不能再赋值,因此必须初始化.

  2. Unity Shader Learning

    Toon 表面没有均匀的阴影. 为了达到这个效果,我们需要一个斜坡图. 其目的是将朗伯光强度NdotL重新映射到另一个值. 使用没有渐变的渐变映射,我们可以强制照明逐步渲染.下图显示了如何使用斜坡图来 ...

  3. 创建线程的第三种方式——使用Callable接口

    Callable是类似于Runnable的接口,实现Callable的类和实现Runnable的类都是可被其他线程执行的任务. 优点:有返回值 缺点:实现繁琐 简单实现: CallableAndFut ...

  4. 2019年3月2日-小雨.md

    2019年3月2日, 星期六 开学已经一周了,时间好像限制了自己进步的脚步,一个人的精力有限,想做好方方面面实在是太难了,有很多事儿最后都没做的完美.相反,自己应该放下繁琐的包袱,简简单单的干一件事儿 ...

  5. MyBatis3系列__04CRUD以及参数处理

    本文将会简单介绍一下MyBatis的CRUD以及结合源码讲解一下MyBatis对参数的处理. 作为一个ORM框架,最基本的使用也就是CRUD了,MyBatis提供了两种方法:xml配置文件和动态注解. ...

  6. python学习笔记(4)

    .................................................................................................... ...

  7. emoji 表情: MySQL如何支持 emoji 表情

    https://www.cnblogs.com/jentary/p/6655471.html 修改数据库字符集: ALTER DATABASE database_name CHARACTER SET ...

  8. web项目部署到服务器中浏览器中显示乱码

    项目部署之后浏览器打开查看时页面乱码 这里可能需要修改一下tomcat配置文件,首先找到Tomcat的安装路径下的conf/server.xml文件,找到之后可以CTRL+F搜索如下的内容: < ...

  9. 常用的Tensor操作

    常用的Tensor操作 1.通过tensor.view方法可以调整tensor的形状,但必须保证调整去前后元素总数一致.view不会修改自身的数据,返回新的tensor与原tensor共享内存,即更改 ...

  10. 微信公众平台测试号 “微信登录失败,redirect_uri域名与后台配置不一致,错误代码10003”

    设置"网页授权获取用户基本信息" 点击"修改" 弹出"OAuth2.0网页授权",注意域名不加"https://"或&q ...