EF 笔记

1. 类与类之间通过引用,即为导航属性,来建立关系,CF会根据引用的属性类型,将其映射为一对一,或一对多,或多对多的关系

  表名生成方式:1)类名的复数(默认的)2)使用特性[Table("TableName")]指定

  3)不想使用表名复数时,可以在OnModelCreating 中加入modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();     

  外键生成方式:1)表名+ID(默认的)2)使用特性[ForeignKey("FKName")]指定

2. 当一个类在加载数据时,默认不会加载外键表数据(懒惰加载:导航属性由virtual修饰和 Configuration.LazyLoadingEnabled = true)

  其它两种加载方式:

  贪婪加载: context.Table1.Include("Table2"), 生成SQL语句,只有一条,相对复杂点

  显示加载: context.Entry(context.Table1.Single()).Collection(d=>d.Table2).Load(); 

      • 注意结合 Query() 和 IsLoaded 的使用,Collection 是一对多的引用,一对一引用,则使用 Reference
      • 执行Load()之后,所有有关Table2的操作都会在内存中进行
      • 这里生成的是两条SQL,执行两次查询

3. 当两类之间多次引用对方时,则会建立组合外键,如何确定关系时,则可在一个类的引用属性上使用InverseProperty("另一类的引用属性名")

4. 当两类之间互相引用对方的类集合时,CF将自动生成包含两类主键的中间表,为两表建立一个多对多的关系

5. 当两类之间互相引用对方的类时,则需在当前类的主键上,设置特性,并把 ForeignKey 指向其引用属性名(另一个类的名称,两表之间为一对一关系

  [Key,ForeginKey("另一个类的名称")]

  public Guid 主键名称 //标识特性Key时,其名称命名可以不用与另一个类的名称作为前缀

6. one to one:在设置外键对象的时候,其它外键的对象跟主表对象 必须都来之同一个上下文

 void AddProject(){ 

 NSContext context = new NSContext();

   IRepository<EmailConfig> emailconfigDAL = new NS.Context.EmailConfigDAL(context);//必须传进去,如果不是同一个上下文,将会报 Cannot insert duplicate key in object “PK_EmailConfig”

   EmailConfig emailconfig = emailconfigDAL.FindAll(new EmailConfig { ID = model.EmailConfig_ID.Value }).First();
   model.ID = Guid.NewGuid();
   model.EmailConfig = emailconfig;//这里
   model.CreateDate = DateTime.Now;
   model.WorkStatus = model.WorkStatus;
   context.Projects.Add(model);
   context.SaveChanges();

}

7.PM> Enable-Migrations 

8. 数据库配置,通过 Fluent API 和 Data Annotation 这两种方式来配置的, 在实际操作中,我们二选一就行

  Data Annotation:通过特性的形式来配置,如:

    

KeyAttribute

StringLengthAttribute

MaxLengthAttribute

ConcurrencyCheckAttribute

RequiredAttribute

TimestampAttribute

ComplexTypeAttribute

ColumnAttribute  

TableAttribute  

InversePropertyAttribute 

ForeignKeyAttribute 

DatabaseGeneratedAttribute   

NotMappedAttribute    

 

  Fluent API:通过在DbContext中的重写 OnModelCreating 来配置的,为避免该方法体过度膨胀,可以为各个类配置相应映射类,如:

    

public class 类的名称Map : EntityTypeConfiguration<类的名称>
    {
        public 类的名称Map()
        {
            Property(d => d.Name).IsRequired();// 这只配置一个要求,如有其它,则可以在自身的映射类中配置
        }
    }

  然后,

 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Configurations.Add(new 类的名称Map());// 这只体现一行代码
        }

如下进行配置,如果有多个配置的话,则会膨胀
protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity
<类的名称>().Property(d => d.Name).IsRequired();
        }

   另外如果不想表与表之间存在级联删除公约,则可以加入

   modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();

   还有其它可以移除的公约(根据需要而定),如:

   OneToOneConstraintIntroductionConvention,IncludeMetadataConvention 等等

 

9. There is already an open DataReader associated with this Command which must be closed first. 异常

  由于导航属性 xxx(具有 virtual 和 LazyLoadingEnabled = true), 在 connectionString 中没有设置 MultipleActiveResultSets=true 引起的

  MARS is compatible with SQL Server 2005 and above

10. 乐观并发控制:

  行版本控制:Version 字段数据类型必须为 byte[] , 然后 this.Property(s => s.Version).IsRowVersion() ,在生成的SQL语句中,将会附带 version='#########' 作为条件,

        如:update table set name='xxx' where id=1 and version='########'

  字段控制: 任意字段都可以这样配置 this.Property(s => s.Email).IsConcurrencyToken(),在生成的SQL语句中,将会附带旧值作为条件,

        如: update table set Email='新值' where id=1 and Email='旧值'

posted @ 2013-05-18 11:11  Yu  阅读(242)  评论(0)    收藏  举报