EF6进修条记二:一些细致设置装备摆设,最先设


玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。

上一篇直接运用Code-first建模体式格局,实在EF供应了三种数据建模体式格局

1 database-first  数据库优先,若是你有一个已设想好的数据库,运用这类体式格局,然后你的数据模型需要合营数据库表来,我没弄过,不说太多

2 model-first  喜好GUI可视化界面举行数据库建模的,运用这类体式格局,我没弄过

3 code -first  代码最大,一定要记着,运用这类体式格局,内心就不要想着数据库,一定要依照我model的设想来给我天生我需要的表组织,我是不会对数据库委屈求全的,EF一定能够或许知足我的请求,险些不存在只要数据能做而EF不克不及做的状况。

大多数的开发人员一定都邑SQL,然后ORM框架又一涌现,那我们对他的进修态度是甚么样的呢?我常常问本身,ADO.NET能做的为何要去弄EF,以是很有能够我用EF搞不定的状况就去依靠ADO。如许能够两种体式格局同时运用,就乱了。

如今我的进修目标就是,我甚么都要用EF搞。

数据库三种建模体式格局,EF的架构也是三层,等会我来弄的数据库初始化战略也是三种体式格局,呵呵!

EF的架构随意说一下

Conceptual Schema Define Layer (CSDL)  观点架构界说层  工具的天下(开发人员面向这一层)

Mapping Schema Layer (MSL)   映照架构层   映照

Storage Schema Define Layer (SSDL) 存储架构界说层   数据的天下(这一层特地和数据库打交道)

这篇博客重要讲讲我用EF举行一些设置装备摆设时遇到的题目,我的目标是能够或许设想一个差不多能够运用的数据模型出来,题目说完了,背面弄个简朴的器械出来

数据库初始化战略

public class EFDbContext:DbContext
    {
        public EFDbContext()
        {
            //  若是数据库不存在就建立
            //Database.SetInitializer(new CreateDatabaseIfNotExists<EFDbContext>());

            //  老是建立数据库
            //Database.SetInitializer(new DropCreateDatabaseAlways<EFDbContext>());

            // 若是model变了就建立数据库
            //Database.SetInitializer(new DropCreateDatabaseIfModelChanges<EFDbContext>());

            //禁用数据库初始化战略
            Database.SetInitializer<EFDbContext>(null);
        }
View Code

 

这个需要在FEDbContext组织函数中设置装备摆设。那这个数据库初始化时做甚么的呢?为何倏忽这个一个器械让你去设置装备摆设呢?实在我并不太邃晓,我试了一下,我运用老是建立数据库这个设置装备摆设,当我每次运转顺序,并在Student表中增加一条纪录。然后我再看我的student表,之前的数据都没了。

以是我以为这个器械必需要显现制止掉。我以为每次运转顺序就初始化数据库这一功用对照合适我如今对EF的进修阶段,能够我的设置装备摆设没弄好,model 设想有题目,那末初始化数据库能够。

个中也遇到一个题目,当我设置装备摆设成老是建立新数据库时,我在运转的时刻报错了

 

他说我的数据库正在运用,我就有点搞不懂了。我也不知道数据库在甚么时刻算是运用中的状况……  岂非是要把数据衔接断开?不能够吧,多是我的查询tab页没封闭?嗯,有能够,我看看这确切还查着数据呢

关了查询,就好了。这个get到了,新建查询就申明数据库在被运用

一些详细的设置装备摆设

如今来看一下我弄的一些详细的设置装备摆设

我新建一个sutdent类,内里有一个只读属性,然后更新到数据库中,并没有建立这个只读属性对应的字段。我以为很惬意,有些器械你不想让他映照到数据库中也能够设置装备摆设

说一下设置装备摆设的体式格局,Data Annotations、Fluent API  第一种就是我用特征的体式格局在属性上或许范例上加上形貌,像这类[POST]、[Key]、[Required];Fluent API fluent流畅的意义。就是经由过程写设置装备摆设代码的体式格局来。界说设置装备摆设都要重写DbContext的一个要领OnModelCreating中举行

一样平常的做法,若是说我要在model的那些属性上加上甚么最大长度、局限、非空……的那些校验,用Data Annotations的体式格局明显要好一些

public class EFDbContext:DbContext
    {
        protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
        {
           //  在这里加上你本身的设置装备摆设,包孕一些全局设置装备摆设、自界说设置装备摆设这些
           //  onModelCreating 在model建立的时刻它设置装备摆设通知它,这没缺点
           //  下面这个是个全局设置装备摆设,一切model中,属性为“Id”的就设置为主键
           //dbModelBuilder.Configurations.
           //dbModelBuilder.Properties()
           //    .Where(x => x.Name == "Id")
           //    .Configure(p => p.IsKey());

          //  下面这个我为Book指定主键为“BooId”
          dbModelBuilder.Entity<Book>().HasKey(x => x.BooID);
        }
}
View Code

 

我们还需要相识一下EF中的默许设置装备摆设,来看主键的默许设置装备摆设

EF中默许的主键为“ID” 或许 类名 “ID”,不辨别大小写,好比我如今的这个Book类

namespace _20190106
{
    public class Book
    {
        public string BooID { get; set; }
        public string Name { get; set; }
        public virtual ICollection<Catalog> Catalogs { get; set; }
    }
}
View Code

 

我的ID为BooID,没有知足他的默许划定规矩,那末我在举行数据迁徙的时刻,就报错,他说我的Book没有界说主键

 

表名复数左券

若是你没有对表名复数左券做设置装备摆设的话, 那末数据库中建立的表名都邑是复数情势,看,我的表名满是复数情势的

对照令我想不到的是,person成了people,让我蓦地一会儿感受到英文的考究……不外,这类器械照样依照我的习气来吧,决定权给我吧,以是,加上一句,禁用掉

 protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
        {
            //删除复数表名左券  //dbModelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
View Code

 EF修正注解天生的SQL语句是如许的,能够随着他进修一下

EXECUTE sp_rename @objname = N'dbo.Catalog', @newname = N'Catalogs', @objtype = N'OBJECT'
IF object_id('[PK_dbo.Catalog]') IS NOT NULL BEGIN
    EXECUTE sp_rename @objname = N'[PK_dbo.Catalog]', @newname = N'PK_dbo.Catalogs', @objtype = N'OBJECT'
END
EXECUTE sp_rename @objname = N'dbo.Library', @newname = N'Libraries', @objtype = N'OBJECT'
IF object_id('[PK_dbo.Library]') IS NOT NULL BEGIN
    EXECUTE sp_rename @objname = N'[PK_dbo.Library]', @newname = N'PK_dbo.Libraries', @objtype = N'OBJECT'
END
View Code

 

来看看庞杂范例,我界说一个person类,一个VO工具(value object ) 内里有个属性是类范例的,我的意义就是以为Adress这三个属性能够归为一组

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。-
public class Person
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public Address Address { get; set; }
    }
    public class Address
    {
        public string Province { get; set; }
        public string City { get; set; }
        public string Area { get; set; }
    }
View Code

 

然后表是如许的,是我想要的,你也能够设置装备摆设,映照成零丁的一张表

然后我们看看一对多的干系,有包罗干系的类,映照会成甚么模样

藏书楼类,内里有许多书,virtual声明的成为导航属性,详细我说不太清晰。其他的设置装备摆设我都没有增加,默许天生的表就是如许的。

能够如许照样不可若是我又一个定单类Order,内里有产物的鸠合List<Product> 那末他默许给我建立的Product中会有一个order的外键

如许应该是不可的,产物表应该是自力的,那退货单呢,不是又要加一个外键?以是如许设想不太好。

这是涉及到一对多的干系了,这里我还没有弄到,一对一,一对多,多对多的组织是重点,我背面去弄。

 

继续干系

类内里一定少不了继续干系啊,以是这里轻微说一下,由于这个我还没弄到这里。

每一个表都有ID,有的另有会AddTime 、IsDelete,那末能够抽出一个基类,让其他的类去继续

public class BaseEntity
    {
        public string ID { get { return Guid.NewGuid().ToString(); } set { } }
        public DateTime AddTime { get { return DateTime.Now; } set { } }
        public bool IsDelete { get { return false; } set { } }
    }
View Code

然后我写一个Teacher类,继续BaseEntity

public class Teacher : BaseEntity
    {
        public string Name { get; set; }
        public string Tel { get; set; }
        public string Subject { get; set; }
    }
View Code

 

我甚么都不设置装备摆设,然后我实行迁徙,将数据模型映照到数据库,接着运转顺序,Main要领中增加一个Teacher实例,并查询打印出来。

报错

未经处置惩罚的非常:  System.InvalidOperationException: The value of a property that is part of an object's key does not match the corresponding property value stored in the ObjectContext.  This can occur if properties that are part of the key return inconsistent or incorrect values or if DetectChanges is not called after changes are made to a property that is part of the key.

然后看看数据库的表组织

 

 

 

他没有将BaseEntity建立为一张表,从基类继续过去的属性悉数在这个Teacher内里,再看看表内里有无数据

表内里是有数据的。为何我查询打印却报错呢?

我想是如许的,查询出来的数据字段包孕基类的属性 子类的属性,然后它在映照的时刻发明我是用子类来吸收的,而子类又没有显现界说基类的那些属性,致使条目不一致,就报错了。

关于继续也是重中之重,继续也有三种体式格局,背面学了再说。

 

我如今我做的就是设想两个类,一个Bug类,一个Developer开发者类,我的这个设想一定不合理

Bug类

public class Bug
    {
        public string ID { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        //  提交时候
        public DateTime SubmitDate { get; set; }
        //  完成时候,修复时候
        public DateTime? CompleteDate { get; set; }
        //  bug状况
        public BugStatusEnum BugStatusEnum { get; set; }
        // bug发生时的体系情况
        public SystemEnvironment VO_SystemEnvironment { get; set; }
        //  只读字段
        public string BugStatusEnumText { get {return  Enum.GetName(typeof(BugStatusEnum), BugStatusEnum); } }
        // 体系级别字段,非营业范畴字段
        public DateTime AddTime { get; set; }
        public bool IsDelete { get; set; }
    }
    //  体系情况
    public class SystemEnvironment
    {
        //  操作体系
        public string OS { get; set; }
        //  可用内存
        public double AvailableMemory { get; set; }
        //  可用磁盘
        public double AvailableDisk { get; set; }
    }
View Code

 

罗列

public enum BugStatusEnum
    {
        已认领 = 10,
        未认领 = 20,
        已修正 = 30
    }
View Code

 

开发者类

//  开发人员
    public class Developer
    {
        public string ID { get; set; }
        public string Name { get; set; }
        public virtual ICollection<Bug> Bugs { get; set; }
    }
View Code

 

设置装备摆设代码

public class EFDbContext : DbContext
    {
        public EFDbContext()
        {
            //  数据库初始化
            //  Database.SetInitializer(new DropCreateDatabaseAlways<EFDbContext>());
        }

        public DbSet<Bug> Bugs { get; set; }
        public DbSet<Developer> Developers { get; set; }

        protected override void OnModelCreating(DbModelBuilder dbModelBuilder)
        {
            dbModelBuilder.Entity<Bug>().ToTable("tb_Bugs");  //  指定表名
            dbModelBuilder.Entity<Bug>().HasKey(x => x.ID);  //  显现指定ID为主键
            dbModelBuilder.Entity<Bug>().Property(p => p.Name).HasMaxLength(100).IsRequired(); // 设置Name属性最长为50,非空
            dbModelBuilder.Entity<Bug>().Property(p => p.ID).HasMaxLength(36).IsRequired();
            dbModelBuilder.Entity<Bug>().Property(p => p.Description).HasMaxLength(500).IsRequired();   //   这里的链式挪用是否是感觉到Fluent了?

            //  移除注解复数左券
            dbModelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        }
}
View Code

 

-玖富娱乐是一家为代理招商,直属主管信息发布为主的资讯网站,同时也兼顾玖富娱乐代理注册登录地址。