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='旧值'

浙公网安备 33010602011771号