• EF--CodeFirst


    EF框架有三种基本的方式:DB First,Model First,Code First。这里简单的说一下Code First,适合没有基础的同学照着做,学习基础的东西。

    通过Code First我们可以在还没有建立数据库的情况下就开始编码,然后通过代码来生成数据库。

    1、还是先建立一个类库项目。(这里忘了说了,和前面两个模式一样,这里我使用的工具是:VS2013,sqlserver2008r2)

    然后创建4个类,这几个类表示数据库中的表的列的定义

    public class User
        {
            public Guid Id { set; get; }
            public string Name { set; get; }
            public int Age { set; get; }
            public Guid RoleId { set; get; }
        }
        public class Role
        {
            public Guid Id { set; get; }
            public string Name { set; get; }
        }
        public class Right
        {
            public Guid Id { set; get; }
            public string Name { set; get; }
        }
        public class UserRight
        {
            public Guid UserId { set; get; }
            public Guid RightId { set; get; }
        }

    2、创建数据库访问的上下文,以便对数据库进行增删改查。上下文中的属性表示数据库中的表

    public class CodeFirstContext : DbContext//这个DbContext必须要添加EntityFramework 5.0的引用才能编译通过
        {
            public DbSet<User> UserSet { get; set; }
            public DbSet<Role> RoleSet { get; set; }
            public DbSet<Right> RightSet { get; set; }
            public DbSet<UserRight> UserRightSet { get; set; }      
    
        } 

    3、在类Class1中定义增删改查的方法,这里与前面两个模式中的Class1是一样的,我就不再重复了,这里只简单的添加一个用于增加数据的函数

    public class Class1
        {
            public int AddUser(){
            User u = new User(){
                   Id=Guid.NewGuid(),
                   Name = "Bali",
                   Age=32
                };
            CodeFirstContext con = new CodeFirstContext();
            try
            {
                con.UserSet.Add(u);
                con.SaveChanges();
            }
            catch (Exception e)
            {
                return 0;
            }
            return 1;
        }
     }

    4、创建一个控制台项目,调用class1中的AddUser函数,运行,这时候需要等待一下,最后看到执行的结果报错了

    意思就是找不到数据库。EF默认的数据库是:.SQLEXPRESS,如果本地没有SQLEXPRESS,EF会尝试LocalDbv11.0(包含在VS2012中) 

    在上面几步中,没有一点是关于数据库的,没有添加链接字符串,所以需要在控制台项目的配置文件中添加如下代码:

    <connectionStrings>
    <add name="CodeFirstContext" providerName="System.Data.SqlClient" connectionString="Server=.;Database=CodeFirst;User ID = sa;Password = 123456;Trusted_Connection=False"/>
    </connectionStrings>

    这个链接字符串的名称是CodeFirstContext,就是数据库上下文的名称

    同时,需要对CodeFirstContext类添加一个构造函数,让上下文能找到数据库:

    public CodeFirstContext() : base("name=CodeFirstContext") { }

    这个时候系统会提示缺少System.Data.Entity的引用,因此要添加上这个引用才行

    5、再次执行,结果又报错

    这里就会发现,之前在定义实体的时候,都没有指定键值和外键(如果有的话),但是为什么偏偏是最后一个实体报错了,前面几个没问题。

    Code First会默认将以类似Id结尾来命名的属性当作主键,如ID,Id,本例中的Id都自动设置为主键。如果该属性是int类型,Code First会在数据库中默认将该列设置为自增长。

    在UserRight实体中没有Id属性,因此系统找不到该让谁来做主键,因此报错。这个问题的解决方案,网上有很多,这里就不做探讨,在此,只做简单的介绍,将遇到的问题解决了。

    如果想要更深的学习,可以参考:http://www.cnblogs.com/caofangsheng/p/5023696.html

    首先是要添加引用

    将UserRight类重新设计,这是复合主键的设置方式,如果是单一主键,只需添加[Key]即可。

    public class UserRight
        {
            [Key]
            [Column(Order = 1)]
            public Guid UserId { set; get; }
            [Key]
            [Column(Order = 2)]
            public Guid RightId { set; get; }
        }

    6、运行,这次是成功了,在添加的user表的时候,没有设置RoleId,但是在数据库中可以看到,这列是系统默认值。这里还有很多的属性约束没有谈到,比如name的类型为什么

    是nvarchar(max)而不是nvarchar(50),为什么name可以为空,而roleid和age却不能为空。这里也不做探讨了,相关的资料网上有。

     7、至此,codefirst模式的基本流程算是走一遍了。那么现在问题来了,如果这个时候数据库里面有数据了,需要添加新的表,或者给表添加列,删除列,或者修改列的类型。

    常规的思路是直接在项目中添加实体,然后再次运行。

    先添加一个实体

    public class Company
        {
            public Guid Id { set; get; }
            public string Name { set; get; }
            public string Address { set; get; }
        }

    然后在上下文类中添加一个属性public DbSet<Company> CompanySet { get; set; }      

    再运行,结果报错

    8、下面介绍数据迁移

    8.1、

     

    在程序包管理器控制台,执行语句:Enable-Migrations或Enable-Migrations –EnableAutomaticMigrations

    结果出现了错误:无法将“Enable-Migrations”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。

    然后输入Get-Package,发现未安装程序包,输入安装命令Install-Package EntityFramework还是有错,发现程序包源和默认项目没有按照图中的设置

    改过来后就成功安装了

    安装完成后,发现上面的EF版本变成最新的6.1.3版了,同时添加了sqlserver的引用。

    8.2、输入Enable-Migrations –EnableAutomaticMigrations

    命令完成后,此时在项目中创建一个Migrations文件夹。该文件夹保存着迁移的升级脚本,记录着一些迁移配置,大部分的时候无需关注。这一步只需要在第一次操作的时候干,平时无需管它。

     8.3、输入Update-Database –Verbose。这样就完成了数据库迁移

    可以看到,companies表已经创建了,而且还多了个__MigrationHistory表,这个不用管它。它里面有如下数据

    可以看到ef版本的变化。

    9、这时候我们又对实体进行修改

    这个时候再次执行Update-Database –Verbose,结果报错

    执行Update-Database –Verbose -force,这个时候就成功了,但是问题也来了。首先看数据库

    数据库的表结构确实如愿以偿的修改了,但是看看users表中的数据,结果数据丢失了

    大部分的时候只需要进行如下两步即可:

    1. 将包管理器的默认项目切换到模板项目
    2. 在程序包管理器中执行 Update-Database –Verbose

    不过,还有如下几个地方需要注意一下: 

    有损升级:如果我们进行了如删除列,限制数据精度的时候,这个时候升级的时候就会出现错误提示,遇到这种情况,首先确保升级是安全的,然后通过增加-force参数强制升级。或者直接修改Configuration.cs的AutomaticMigrationDataLossAllowed选项,放开有损升级检查。(不大建议)

    不兼容的升级:如果我们进行了加入了非空列,要进行数据转换等不兼容的升级的时候,自动升级会失败,这个时候则需要和传统的迁移方式那样构造升级代码,比较麻烦,且容易出错。如果没有特殊需求不建议进行不兼容的升级。

    从上面的步骤看来,codefirst模式真的很麻烦,而且很容易出错,有些错误会让人感觉莫名其妙,同样的操作步骤,第一次还能成功,但第二次就会失败。这样的问题太多,导致

    codefirst模式用起来不爽(也许是本人技术不行,没有吃透)。这三种模式,我觉得最好用的还是DBFirst,它首先要求在sqlserver中将数据库设计好,这与以前的数据库搭建没什么

    区别,然后通过创建ado.net实体数据模型,选择从数据库生成的方式来创建实体,进而对数据库增删改查。如果对数据库有变更,那也是先在sqlserver中变更好了,再在实体模型中对变更的地方重新导入即可,整个过程稳定不会出现莫名其妙的错误。而modelfirst完全就是dbfirst的反操作。麻烦的地方就是如果需要变更数据库,首先得在实体模型中变更,完了后会产生一个sql文件,这个时候还不能执行这个sql文件,需要将不必要的sql语句屏蔽后才能执行。如果数据库没有数据或者表比较少的时候,还可以接受,否则每次对数据库有变更都需要手动的去sqlserver中更改,同时还得担心万一有人一不小心执行了sql文件,结果导致原来的数据全部丢失,那乐子就大了

  • 相关阅读:
    数据的独立同分布检验
    基于密度聚类的DBSCAN和kmeans算法比较
    Python 爬虫笔记、多线程、xml解析、基础笔记(不定时更新)
    多进程之multiprocessing模块、守护进程、互斥锁
    程序与进程的区别,并发与并行的区别,多进程的实现原理
    并发编程之守护进程
    MySQL帮助文档的使用
    MySQL操作之DCL
    MySQL操作之DML
    MySQL操作之DDL
  • 原文地址:https://www.cnblogs.com/jin-/p/6594067.html
Copyright © 2020-2023  润新知