• Mysql通过CodeFirst方式使用EF


    1MySql环境准备

    (1)ADO.NET driver

    安装ADO.NET操作MySql的驱动“Connector/NET”,下载地址如下:

    https://dev.mysql.com/downloads/connector/net/8.0.html

    (2)VS访问MySql对象的支持(包括Entity Framework

    A、通过安装“MySQL for Visual Studio”以支持访问MySql对象及VS的设计器

    https://dev.mysql.com/downloads/windows/visualstudio/

    B、通过NuGet安装“MySql.Data.Entity.EF6”以支持访问MySql对象

     

    2、配置

    (1)EntityFramework

    通过NuGet安装EntityFramework,安装完后会自动在config里添加如下的section

    <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>

    驱动(默认为MSSql驱动,及指向的本地DB的实例MSSQLLocalDB-VS自带的简单的DB):

    <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>

    (2)MySql.Data.MySqlClient驱动

    通过“1.2”的方式安装后,需确保项目引用到了如下两个组件

     

    否则在程序集里添加

     

    在config里会自动添加或需手动指定EF的适配器

    <entityFramework>
        <providers>
          <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.9.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></provider>
        </providers>
    </entityFramework>

    (3)connectionString

    通过connectionString配置的连接串的优先级大于defaultConnectionFactory

    <connectionStrings>
        <!--Mysql:MultipleActiveResultSets,App=EntityFramework不支持-->
        <add name="ModelCaiji" connectionString="data source=localhost;initial catalog=XXX;user id=XXX;password=XXX;integrated security=True;" providerName="MySql.Data.MySqlClient"/>
    </connectionStrings>

    (4)注意

    A、无法为具有固定名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序加载在应用程序配置文件中注册的实体框架提供程序类。

    需要确保对DLL以应用,及版本后的正确。

    https://blog.csdn.net/QQ459932400/article/details/58068551

    B、利用VS自带的命令行工具查看PublicKeyToken

    SN –T “XXXXXXXXXXXXXX.dll”

    https://blog.csdn.net/kuui_chiu/article/details/6914049

    3、实现

    (1)DB上下文类

    通过添加空的Code First模型或者手工添加类继承DbContext

     

    配置好对应的connectionString后即可通过EF访问DB

    using (ModelCaiji context=new ModelCaiji())
                {
                   var query= context.Database.SqlQuery<string>("select Name from filminfo;");
                    return query.ToList();
                }

    (2)实体及与table的映射

    添加实体及与table的映射以便支持相应实体的操作及生成DB

        /// <summary>
        /// 实体
        /// </summary>
        public class FilminfoEntity
        {
            public int Id { get; set; }
            public string Name { get; set; }
        }
    
        /// <summary>
        /// 实体与数据表的映射(Fluent API)
        /// </summary>
        public class FilminfoEntityMap : EntityTypeConfiguration<FilminfoEntity>
        {
            public FilminfoEntityMap()
            {
                #region Generated
                //ToTable("filminfo");
    
                HasKey(table => table.Id);
    
                Property(table => table.Id)
                    .HasColumnName("Id")
                    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
                    .IsRequired();
                Property(table => table.Name)
                    .HasColumnName("Name");
                #endregion Generated
            }
        }

    (3)DB初始化策略

    EF上下文支持如下初始化DB的策略

            public ModelCaiji()
                : base("name=ModelCaiji")
            {
                //数据库初始化策略
                //Database.SetInitializer<ModelCaiji>(new CreateDatabaseIfNotExists<ModelCaiji>());//(默认策略)如果数据库不存在,那么就创建数据库。
                //Database.SetInitializer<ModelCaiji>(new DropCreateDatabaseIfModelChanges<ModelCaiji>());//如果模型变化了,数据库就会被重新创建,原来的数据库被删除掉了。
                //Database.SetInitializer<ModelCaiji>(new DropCreateDatabaseAlways<ModelCaiji>());//每次运行程序都会重新创建数据库,这在开发和调试的时候非常有用。
                Database.SetInitializer<ModelCaiji>(null);//关闭策略,不自动创建DB
                //Database.SetInitializer<ModelCaiji>(new CustomDatabaseInitializer<ModelCaiji>());//自定义策略
            }

    自定义策略:

        /// <summary>
        /// 自定义数据库初始化策略
        /// </summary>
        public class CustomDatabaseInitializer<TModelCaiji> : DropCreateDatabaseAlways<TModelCaiji> where TModelCaiji : ModelCaiji
        {
            protected override void Seed(TModelCaiji context)
            {
                //添加电影数据
                FilminfoEntity filminfoEntity = new FilminfoEntity()
                {
                    Name = "斗破苍穹"
                };
    
                context.FilminfoEntity.Add(filminfoEntity);
                base.Seed(context);
    
            }
    
        }

    (4)约定

    可移除EF自带的约定

    protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
            {
                //添加实体与数据表的映射
                modelBuilder.Configurations.Add(new FilminfoEntityMap());
    
                //移除约定
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();//(移除此约定将不会改变DbSet对应的表名)如果在Map里没有明确指定表名,将使用DbSet实体集的名称当作表名并且会强制转会为复数格式
                modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();//移除级联删除
                modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
                
            }

    4、其它

    (1) DbContext实例初始化问题

    A、对于一般的BS系统为了提高与DB交互的性能需确保数据库上下文DbContext对象在同一操作线程内唯一

                    //CallContext:是线程内部唯一的独用的数据槽(一块内存空间)
                    //传递DbContext进去获取实例的信息,在这里进行强制转换。
                    AppDbContext dbContext = CallContext.GetData("DbContext") as AppDbContext;
                    if (dbContext == null) //线程在数据槽里面没有此上下文
                    {
                        lock (_lockObj)
                        {
                            if (dbContext == null)
                            {
                                dbContext = new AppDbContext(); //如果不存在上下文的话,创建一个EF上下文
                                //我们在创建一个,放到数据槽中去
                                CallContext.SetData("DbContext", dbContext);
                            }
                        }
                    }
                    return dbContext;

    B、对于类似多线程的环境需避免数据库上下文DbContext对象重复使用

    https://blog.csdn.net/u011127019/article/details/54576703

    5、参考

    Entity Framework 6官方文档

    https://docs.microsoft.com/zh-cn/ef/ef6/index

    Entity Framework 5.0 Code First全面学习

    https://blog.csdn.net/gentle_wolf/article/details/14004345

    EF三种编程方式的区别Database first ,Model first ,code first

    https://www.cnblogs.com/gaodaoheng/articles/6489918.html

    EF 配置(SqlServer,Mysql)

    https://www.cnblogs.com/NatureSex/p/3408021.html

    EF Code First:实体映射,数据迁移,重构

    http://developer.51cto.com/art/201309/409947_all.htm

  • 相关阅读:
    C语言练习之计算某年日是该年的第几天
    C语言练习之 猴子吃桃问题
    C语言练习之 求阶乘
    C语言学习(四)
    C语言学习(三)
    C语言学习(二)
    C语言学习(一)
    自定义函数汇总
    #2019121200026 最大子序列和
    #2019121000025-LGTD
  • 原文地址:https://www.cnblogs.com/hepc/p/9545045.html
Copyright © 2020-2023  润新知