zoukankan      html  css  js  c++  java
  • 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例

     【转载自https://segmentfault.com/a/1190000004152660】

    [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例

    本文我们来学习一下在Entity Framework中使用Context删除多对多关系的实体是如何来实现的。我们将以一个具体的控制台小实例来了解和学习整个实现Entity Framework 多对多关系的实体删除的操作过程。

    你将学习到

    • 怎样创建一个引用Entity Framework的项目;

    • 怎样配置Entity Framework的数据库连接;

    • 怎样去掉Entity Framework Code First 生成的表名的复数;

    • 怎样通过EntityTypeConfiguartion<T>配置实体的Fluent API ;

    • 怎样配置Entity Framework的实体多对多的关系映射;

    • Entity Framework数据初始化;

    • 怎样使用包管理工具控制台来生成和更新数据库;

    • 怎么删除Entity Framework中的多对多关系的数据。

    本示例开发环境

    • 操作系统:Windows 10

    • 开发工具及版本:Visual Studio 2015 Update 1

    • .NET Framework版本:.NET Framework 4.6

    • 程序输出方式:控制台应用程序

    第一步、创建项目并引用程序包

    1.1 创建项目

    首先,我们创建一个控制台应用程序,取名为:EFRemoveManyToManyDemo,如下图:

    1.2 引用程序包

    接着打开程序包管理工具,安装必须的EntityFramework引用包,如下:

    第二步、创建实体类并配置数据库连接

    2.1 创建实体类

    安装好Entity Framework包之后 ,我们先创建本示例需要的两个实体对应的类:User和Role(都放在Model的文件夹下),如下:

    User.cs

     1 using System;
     2 using System.Collections.Generic;
     3 
     4 namespace EFRemoveManyToManyDemo.Model
     5 {
     6     public class User
     7     {
     8         public User()
     9         {
    10             Roles = new HashSet<Role>();
    11         }
    12         public int Id { get; set; }
    13         public string FirstName { get; set; }
    14         public string LastName { get; set; }
    15         public DateTime? CreatedOn { get; set; }
    16         public virtual ICollection<Role> Roles { get; set; }//多对多关系中两边都要写上ICollection
    17     }
    18 }

    Role.cs

     1 using System.Collections.Generic;
     2 
     3 namespace EFRemoveManyToManyDemo.Model
     4 {
     5     public class Role
     6     {
     7         public Role()
     8         {
     9             this.Users = new HashSet<User>();!!依赖注入中的构造器注入
    10         }
    11         public int Id { get; set; }
    12         public string Name { get; set; }
    13 
    14         public virtual ICollection<User> Users { get; set; }
    15         //多对多关系中两边都要写上ICollection
    16     }
    17 }

    2.2 配置Fluent API

    为了配置Fluent API,新建一个Mapping文件夹,再分别创建User的配置文件UserConfigurationMapping和Role的配置文件RoleConfigurationMapping,如下:

    UserConfiguration.cs

    using EFRemoveManyToManyDemo.Model;
    using System.Data.Entity.ModelConfiguration;
    
    namespace EFRemoveManyToManyDemo.Mapping
    {
        public class UserConfigurationMapping : EntityTypeConfiguration<User>
        {
            public UserConfigurationMapping()
            {
                Property(x => x.FirstName).HasMaxLength(50).IsRequired();
                Property(x => x.LastName).HasMaxLength(50).IsRequired();
            }
        }
    }

    RoleConfigurationMapping.cs

     1 using EFRemoveManyToManyDemo.Model;
     2 using System.Data.Entity.ModelConfiguration;
     3 
     4 namespace EFRemoveManyToManyDemo.Mapping
     5 {
     6     public class RoleConfigurationMapping : EntityTypeConfiguration<Role>
     7     {
     8         public RoleConfigurationMapping()
     9         {
    10             HasKey(x => x.Id);
    11             Property(x => x.Name).HasMaxLength(50).IsRequired();
    12             HasMany(x => x.Users)
    13                 .WithMany(x => x.Roles)
    14                 .Map(m =>
    15                 {
    16                     m.MapLeftKey("RoleId");
    17                     m.MapRightKey("UserId");
    18                     m.ToTable("LNK_User_Role");
    19                 });
    20         }
    21     }
    22 }

    2.3 创建Context类

    接下来,我们再创建一个名为:ManyToManyRemoveContext的类,该类继承至DbContext类,用于管理数据库的连接上下文和数据库初始化等的一些配置和操作,如下:

    using EFRemoveManyToManyDemo.Mapping;
    using System.Data.Entity;
    using System.Data.Entity.ModelConfiguration.Conventions;
    
    namespace EFRemoveManyToManyDemo
    {
        public class ManyToManyRemoveContext : DbContext
        {
            public ManyToManyRemoveContext() : base("ManyToManyRemoveContext")
            {
    
            }
        }
    }

    2.4 配置连接字符串

    再在App.config配置文件中添加本地的数据库连接字符串,大致如下(具体的请根据你的实际数据连接参数来):

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
        <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
        <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
      </configSections>
      <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
      </startup>
      <connectionStrings>
        <add name="ManyToManyRemoveContext" connectionString="server=你的数据库服务器地址;database=ManyToManyRemoveDemo;uid=你的数据库登录名;pwd=密码" providerName="System.Data.SqlClient"/>
      </connectionStrings>
      <entityFramework>
        <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
          <parameters>
            <parameter value="mssqllocaldb" />
          </parameters>
        </defaultConnectionFactory>
        <providers>
          <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
        </providers>
      </entityFramework>
    </configuration>

    2.5 重写Context

    为了将我们刚才写的Fluent API应用到对应的实体上,所以我们需要重写(override)DbContext的OnModelCreating方法,如下:

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    
                modelBuilder.Configurations.Add(new UserConfigurationMapping());
                modelBuilder.Configurations.Add(new RoleConfigurationMapping());
            }

    其中

    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

      是将Entity Framework Code First在实体类生成对应表时去掉表名的复数用的。简单地说就是,默认情况下,Entity Framework Code First在由实体类生成对应表时的表名是复数形式的,比如本例的User和Role类,如果没有这句配置,在生成表名的时候将会是Users和Roles这两个表名,反之,则是User和Role这两个表名。

    好了,下面贴出完整的ManyToManyRemoveContext.cs文件的代码:

     1 using EFRemoveManyToManyDemo.Mapping;
     2 using EFRemoveManyToManyDemo.Model;
     3 using System.Data.Entity;
     4 using System.Data.Entity.ModelConfiguration.Conventions;
     5 
     6 namespace EFRemoveManyToManyDemo
     7 {
     8     public class ManyToManyRemoveContext : DbContext
     9     {
    10         public ManyToManyRemoveContext() : base("ManyToManyRemoveContext")
    11         {
    12 
    13         }
    14 
    15         protected override void OnModelCreating(DbModelBuilder modelBuilder)
    16         {
    17             base.OnModelCreating(modelBuilder);
    18             modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    19 
    20             modelBuilder.Configurations.Add(new UserConfigurationMapping());
    21             modelBuilder.Configurations.Add(new RoleConfigurationMapping());
    22         }
    23 
    24         public DbSet<User> Users { get; set; }
    25         public DbSet<Role> Roles { get; set; }
    26     }
    27 }

    本文写到这里,关于Entity Framework的引用,实体类的声明和Fluent API配置以及与数据库连接等操作都已完成了。接下来我们要做的是利用Entity Framework所实体生成到配置好的数据库中。

    第三步、应用Migration生成数据库

    在接下来的过程中,我们会用到包管理控制台(Package Manager Console)和三个命令:

    3.1 Enable-Migrations

    命令使用方式如下图:

    运行以上命令后,Entity Framework会自动在我们的项目中创建一个名为Migrations的文件夹,同时生成一个Configuartion.cs的配置文件。这时的项目结构大致是这样的:

    生成好Configuration.cs的文件我们再作数据的初始化,如下:

    namespace EFRemoveManyToManyDemo.Migrations
    {
        using Model;
        using System;
        using System.Collections.Generic;
        using System.Data.Entity.Migrations;
        using System.Linq;
        internal sealed class Configuration : DbMigrationsConfiguration<ManyToManyRemoveContext>
        {
            public Configuration()
            {
                AutomaticMigrationsEnabled = false;
            }
    
            protected override void Seed(ManyToManyRemoveContext context)
            {
                var roles = new List<Role> {
                    new Role{ Id=1,Name="超级管理员" },
                    new Role{ Id=2,Name="管理员" },
                    new Role{ Id=3,Name="一般用户" }
                };
    
                var users = new List<User> {
                    new User {Id=1,FirstName="Kobe",LastName="Bryant",CreatedOn=DateTime.Now,Roles=roles },
                     new User {Id=2,FirstName="Chris",LastName="Paul",CreatedOn=DateTime.Now,Roles=roles.Where(x=>x.Id==2).ToList() },
                     new User {Id=3,FirstName="Jerimy",LastName="Lin",CreatedOn=DateTime.Now,Roles=roles.Take(2).ToList() }
                };
            }
        }
    }

    完成第一个命令和数据初始化配置后,我们进行第二个命令。

    3.2 Add-Migration Init -Verbose

    执行此命令后,会在Migrations的文件夹中自动生成一个形如:时间戳_Init.cs的数据迁移文件,如本例生成的是201512040507219_Init.cs这样一个文件名,其中Init是我们指定的本次数据迁移的版本名称,文件中的内容如下:

     1 namespace EFRemoveManyToManyDemo.Migrations
     2 {
     3     using System;
     4     using System.Data.Entity.Migrations;
     5     
     6     public partial class Init : DbMigration
     7     {
     8         public override void Up()
     9         {
    10             CreateTable(
    11                 "dbo.Role",
    12                 c => new
    13                     {
    14                         Id = c.Int(nullable: false, identity: true),
    15                         Name = c.String(nullable: false, maxLength: 50),
    16                     })
    17                 .PrimaryKey(t => t.Id);
    18             
    19             CreateTable(
    20                 "dbo.User",
    21                 c => new
    22                     {
    23                         Id = c.Int(nullable: false, identity: true),
    24                         FirstName = c.String(nullable: false, maxLength: 50),
    25                         LastName = c.String(nullable: false, maxLength: 50),
    26                         CreatedOn = c.DateTime(),
    27                     })
    28                 .PrimaryKey(t => t.Id);
    29             
    30             CreateTable(
    31                 "dbo.LNK_User_Role",
    32                 c => new
    33                     {
    34                         RoleId = c.Int(nullable: false),
    35                         UserId = c.Int(nullable: false),
    36                     })
    37                 .PrimaryKey(t => new { t.RoleId, t.UserId })
    38                 .ForeignKey("dbo.Role", t => t.RoleId, cascadeDelete: true)
    39                 .ForeignKey("dbo.User", t => t.UserId, cascadeDelete: true)
    40                 .Index(t => t.RoleId)
    41                 .Index(t => t.UserId);
    42             
    43         }
    44         
    45         public override void Down()
    46         {
    47             DropForeignKey("dbo.LNK_User_Role", "UserId", "dbo.User");
    48             DropForeignKey("dbo.LNK_User_Role", "RoleId", "dbo.Role");
    49             DropIndex("dbo.LNK_User_Role", new[] { "UserId" });
    50             DropIndex("dbo.LNK_User_Role", new[] { "RoleId" });
    51             DropTable("dbo.LNK_User_Role");
    52             DropTable("dbo.User");
    53             DropTable("dbo.Role");
    54         }
    55     }
    56 }

    我们可以通过这个文件中的内容看到,有Up()和Down()这两个方法,Up()方法要执行的其实就是本次数据迁移要对数据进行的操作,而Down()方法则是在以后我们如果要退回到此版本应该执行的操作。

    经过以上两个命令,如你迫不及待地要去数据库管理工具中查看有一个名叫:ManyToManyRemoveDemo的数据库是否已生成,那么很遗憾地告诉你,还没有。这时,我们还得执行最后一个命令来生成数据库和实体对应的表。

    3.3 Update-Database -Verbose

    执行以上命令,我们这时再打开数据库管理工具。没错ManyToManyRemoveDemo就在那里。再查看表是否成功生成呢,再检查一下表中是否有我们初始化的数据呢,没错,这些都是可以有的。怎么样,惊喜吧,欢呼吧,我们做到了!!!

    但还没完,请先回复平静,这还只是一个开始。Entity Framework还可以做得更多,我们需要学习的也还有很多,编程的道路从来就不是一步到位的,得有个过程。一步一步往下看吧。

    第四步、增、删、改、查操作

    4.1 查询数据示例

    打开我们项目的Program.cs文件。首先,我们来查询(Query)一下数据库中的数据,如下:

     1 static void Main(string[] args)
     2         {
     3             Query();
     4             ReadKey();
     5         }
     6 
     7         static void Query()
     8         {
     9             using (var cxt = new ManyToManyRemoveContext())
    10             {
    11                 var users = cxt.Users.ToList();
    12                 users.ForEach(x =>
    13                 {
    14                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}
     |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
    15                 });
    16             }
    17         }

    运行结果如图:

    4.2 更新数据示例

    再来更新一条数据库中的数据怎么样,如下:

     1  static void Main(string[] args)
     2         {
     3             Update();
     4             Query();
     5             ReadKey();
     6         }
     7 
     8 static void Query()
     9         {
    10             using (var cxt = new ManyToManyRemoveContext())
    11             {
    12                 var users = cxt.Users.ToList();
    13                 users.ForEach(x =>
    14                 {
    15                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}
     |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
    16                 });
    17             }
    18         }
    19 
    20 static void Update()
    21         {
    22             using (var cxt = new ManyToManyRemoveContext())
    23             {
    24                 var user = cxt.Users.FirstOrDefault(x=>x.Id==3);
    25                 user.FirstName = "ShuHao";
    26                 cxt.SaveChanges();
    27             }
    28         }

    运行结果如我们所料,如图:

    4.3 删除数据示例

    Id为3的User的FirstName已经从数据库更新了。同样的,我们要完成删除操作也比较简,如下:

    1  static void Remove()
    2         {
    3             using (var cxt = new ManyToManyRemoveContext())
    4             {
    5                 var user = cxt.Users.FirstOrDefault(x=>x.Id==2);
    6                 cxt.Users.Remove(user);
    7                 cxt.SaveChanges();
    8             }
    9         }

    4.4 新增数据示例

    就不再贴图了。最后是添加操作,向User表添加一个用户并分配一个Id为1的角色,代码如下:

     1 static void Add()
     2         {
     3             List<Role> roles;
     4             using (var cxt = new ManyToManyRemoveContext())
     5             {
     6                 roles = cxt.Roles.ToList();
     7                 cxt.Users.Add(new User
     8                 {
     9                     Id = 4,
    10                     FirstName = "Console",
    11                     LastName = "App",
    12                     CreatedOn = DateTime.Now,
    13                     Roles = roles.Where(x => x.Id == 1).ToList()
    14                 });
    15             }
    16         }

    4.5 删除多对多数据的示例

    好了,以上是对User(用户实体)进行简单的增、删、改、查的操作,那么我们要实现多对多的删除操作呢?也就是删除用户的同时删除其对应的角色,实现的代码如下:

     1 static void RemoveManyToMany()
     2         {
     3             using (var cxt = new ManyToManyRemoveContext())
     4             {
     5                 var user = cxt.Users.FirstOrDefault(x => x.Id == 1);
     6                 var roles = new List<Role>();
     7                 roles.AddRange(user.Roles.Select(x => x));
     8                 foreach (var role in roles)
     9                 {
    10                     user.Roles.Remove(role);
    11                 }
    12                 cxt.Users.Remove(user);
    13                 cxt.SaveChanges();
    14             }
    15         }

    运行结果如图:

    完整示例代码及下载地址

    好了,最后把Program.cs这个测试文件贴上来,供参考:

     1 using EFRemoveManyToManyDemo.Model;
     2 using System;
     3 using System.Collections.Generic;
     4 using System.Linq;
     5 using static System.Console;
     6 
     7 namespace EFRemoveManyToManyDemo
     8 {
     9     public class Program
    10     {
    11         static void Main(string[] args)
    12         {
    13             //Update();
    14             WriteLine("Before many to many removed");
    15             Query();
    16             RemoveManyToMany();
    17             WriteLine("After many to many removed");
    18             Query();
    19             ReadKey();
    20         }
    21 
    22         static void Query()
    23         {
    24             using (var cxt = new ManyToManyRemoveContext())
    25             {
    26                 var users = cxt.Users.ToList();
    27                 users.ForEach(x =>
    28                 {
    29                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}
     |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
    30                 });
    31             }
    32         }
    33 
    34         static void Add()
    35         {
    36             List<Role> roles;
    37             using (var cxt = new ManyToManyRemoveContext())
    38             {
    39                 roles = cxt.Roles.ToList();
    40                 cxt.Users.Add(new User
    41                 {
    42                     Id = 4,
    43                     FirstName = "Console",
    44                     LastName = "App",
    45                     CreatedOn = DateTime.Now,
    46                     Roles = roles.Where(x => x.Id == 1).ToList()
    47                 });
    48             }
    49         }
    50 
    51         static void Update()
    52         {
    53             using (var cxt = new ManyToManyRemoveContext())
    54             {
    55                 var user = cxt.Users.FirstOrDefault(x => x.Id == 3);
    56                 user.FirstName = "ShuHao";
    57                 cxt.SaveChanges();
    58             }
    59         }
    60 
    61         static void Remove()
    62         {
    63             using (var cxt = new ManyToManyRemoveContext())
    64             {
    65                 var user = cxt.Users.FirstOrDefault(x => x.Id == 2);
    66                 cxt.Users.Remove(user);
    67                 cxt.SaveChanges();
    68             }
    69         }
    70 
    71         static void RemoveManyToMany()
    72         {
    73             using (var cxt = new ManyToManyRemoveContext())
    74             {
    75                 var user = cxt.Users.FirstOrDefault(x => x.Id == 1);
    76                 var roles = new List<Role>();
    77                 roles.AddRange(user.Roles.Select(x => x));
    78                 foreach (var role in roles)
    79                 {
    80                     user.Roles.Remove(role);
    81                 }
    82                 cxt.Users.Remove(user);
    83                 cxt.SaveChanges();
    84             }
    85         }
    86     }
    87 }
  • 相关阅读:
    Python测试开发Tkinter-----(Button--按钮)
    Python测试开发Tkinter------(Frame--框架)
    Python测试开发Tkinter-----(Tkinter--创建顶层窗口及Label)
    python2.7 Scripts环境变量配置 requests bs4 selenium安装方法
    重要知识点:内网系列
    重点知识:系统区分法,响应码,client-ip限制,抓https包的方法
    重点知识:MD5
    01渗透测试基础
    渗透测试之信息收集篇
    sqlmap安装与使用基础
  • 原文地址:https://www.cnblogs.com/xiyin/p/6108233.html
Copyright © 2011-2022 走看看