Entity Framework 4 第二篇 POCO 2
Entity Framework 4第二篇 POCO 2
本篇,继续介绍关于EF 4中的POCO有关数据定义(DDL)方面的东西,比如:指定主键,设置字段长度,指定浮点字段的精度,设置关系,约束,延迟加载等内容。相比EFV1来说,EF 4的确改进了不少。
第0步,准备工作:
需要的环境:Windows 7+VS2010beta2+EF4CTP2+SQL SERVER2008
第1步,建立数据模型类。例如,我们分别写了Company和Person两个类文件。为方便查看各种类型(如:string,decimal,byte[],bool,int,long,datetime)的字段最终映射到数据库表结构中情况,特意尽量使用了比较多的类型。Company实体类具体代码如下:
/// <summary>
/// 对应数据库的Company表
/// </summary>
public class Company
{
public long ID { get; set; }
public string Name { get; set; }
public string HomePage { get; set; }
public virtual ICollection<Person> Persons { get; set; }
}
在Company的POCO类文件中,我们使用了virtual修饰符来修饰集合Persons,这样以便创建代理类以便延迟加载时使用。下面是Person实体类代码:
/// <summary>
/// 对应数据库中的Person
/// </summary>
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public string Position { get; set; }
public Company PersonCompany { get; set; }
public DateTime BirthDay { get; set; }
public byte[] Photo { get; set; }
public Decimal Salary { get; set; }
public string Address { get; set; }
public bool IsMale { get; set; }
}
第2步,设置字段属性和关系等。EF4中提供了EntityConfiguration<TEntity>这个类,我们就是通过它用来指定各种实体类的字段属性和关系等。因此,我们需要自己编写继承EntityConfiguration的实体类配置文件。代码如下:
/// <summary>
/// Company的配置类
/// </summary>
public class CompanyCfg : EntityConfiguration<Company>
{
public CompanyCfg()
{
Property(c => c.ID).IsIdentity();
Property(c => c.Name).HasMaxLength(32).IsRequired();
Property(c => c.HomePage).IsOptional().HasMaxLength(128);
//1..*的关系
Relationship(c => c.Persons).IsOptional();
//设置反向,关系有子对象Person来维护
Relationship(c => c.Persons).FromProperty(p => p.PersonCompany);
}
}
/// <summary>
/// Person的配置类
/// </summary>
public class PersonCfg : EntityConfiguration<Person>
{
public PersonCfg()
{
Property(p => p.ID).IsIdentity();
Property(p => p.Name).HasMaxLength(32).IsRequired();
Property(p => p.Position).HasMaxLength(32);
Property(p => p.Salary).HasPrecision(10, 2);
Property(p => p.Address).HasMaxLength(128);
Property(p => p.Photo).IsMax();
Relationship(p => p.PersonCompany).IsRequired();
Relationship(p => p.PersonCompany).FromProperty(c => c.Persons);
}
}
在代码中,各个方法说明如下:
l IsIdentity()表示是主键标识;
l HasMaxLength()用来指定字段长度;
l IsRequired()用来指定字段比填(不能为空);
l HasPrecision()用来指定浮点类型字段的数据位数和精度;
l IsMax()则设置字段类最大长度为此类型的默认最大长度;
l IsOptional()表示可选即可为NULL;
l Relationship()用来设置关系;
l HasConstraint()用来设置约束
第3步,运行代码。最后,我们需要使用ContextBuilder中的Configurations.Add方法,将上面配置添加到当前的上下文中。代码如下:
[TestMethod]
public void TestMethod1()
{
//
// TODO: Add test logic here
//
SqlConnection con = new SqlConnection(@"Data Source=.\SQLEXPRESS;user id=sa;PassWord=11111111;Initial Catalog=NewNorthwind");
var builder = new ContextBuilder<POCOContext>();
//Add配置类的顺序无关
builder.Configurations.Add(new PersonCfg());
builder.Configurations.Add(new CompanyCfg());
POCOContext context = builder.Create(con);
if (context.DatabaseExists())
context.DeleteDatabase();
context.CreateDatabase();
}
最后,运行上面的,我们可以看到将在数据库建立了两张表。如下图所示:
仔细对比发现:最终的表结构和我最开始想的不一样呢(如:Person表的BirthDay字段不可为空,我开始认为没有在配置类设置的字段应该是默认可空)。
原来,实体类中属性类型是可以Nullable的,在创建表结构时如果没有指定IsRequired,则默认创建的表结构中是可为NULL。实体类中属性类型不能是Nullable的,在创建表结构时,如果没有指定IsRequired,则默认创建的表结构是不能为NULL的。如:Person中,改为public DateTime? BirthDay { get; set; }则创建的表结构中BirthDay可为NULL。
个人觉得,通过这样自己写代码Code Only来实现对数据表进行定义,没有了EDMX文件。总觉得EDMX文件包含所有表的描述、定义、映射,手动修改起来很是不方便。这样相比之下,写代码实现看上去的确是清爽了不少。但是,如果表比较多,表间关系比较复杂的话,估计写代码也容易弄混了。