【原文地址】Feature CTP Walkthrough: Code Only for the Entity Framework
【原文发表日期】 22 June 09 02:54 PM
1) 创建一个名叫“"CodeOnlyWalkthru"”的控制台应用:
2) 往"CodeOnlyWalkThru"解决方案中加一个新的项目:
3) 选择“类库”,将其命名为"Entities":
4) 在你的Entities项目中加一个"Category"类:
右击Entities项目,加一个名叫“"Category"”的类,然后将下面的代码粘贴入该类:
public class Category
{
private List<Product> _products;
public int ID { get; set; }
public string Name { get; set; }
public virtual List<Product> Products {
get
{
if (_products == null)
_products = new List<Product>();
return _products;
}
set
{
_products = value;
}
}
}
5) 生成"Product"类:
在"Category.cs"类中,右击还不存在的Product类名,从上下文菜单上选择"Generate > Class(生成类)":
在新的Product类中,粘贴入下面这些代码:
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
}
至此,你的项目应该象这样:
我们把这些实体类放进了一个单独的项目,这样它们会被编译进一个对Entity Framework无依赖的程序集中。因此,Entities程序集对持久性是透明的,这对一些开发人员来说,是非常重要的。对持久性有意识的代码存在于另外的程序集中,引用对持久性是透明的程序集。
6) 在"CodeOnlyWalkThru"项目中,添加对Entities项目的引用:
7) 在"CodeOnlyWalkThru"项目中,添加对"System.Data.Entity" 和 "Microsoft.Data.Entity.Ctp"的引用:
注: 从长远看来,我们计划将“Code Only”的功能并入核心的Entity Framework程序集。之后,你就只需第一个引用。
8) 在"CodeOnlyWalkThru" 项目中,加一个新的叫"ProductDBContext"的类:
9) 将下面的代码加到"ProductDBContext"类中:
public class ProductDBContext: ObjectContext
{
public ProductDBContext(EntityConnection connection)
: base(connection, "ProductDBContext")
{
ContextOptions.DeferredLoadingEnabled = true;
}
public IObjectSet<Category> Categories
{
get { return CreateObjectSet<Category>(); }
}
public IObjectSet<Product> Products
{
get { return CreateObjectSet<Product>(); }
}
}
因为这个类扩充了ObjectContext,它代表你的模型的形状,起通往你的数据库的入口的作用。注意,我们为上面两个实体类型创建了对应的ObjectSet集。 我们还加了一个构造器,它接受一个EntityConnection参数。ContextBuilder会制造一个EntityConnection (EntityConnection封装了实际的数据库连接和Entity Framework元数据(metadata)),在我们要求它生成一个ProductDBContext新实例时,会将该参数传给这个构造器。在构造器中,我们还配置Entity Framework启用DeferredLoading(即LazyLoading-懒式装载)。
10) 然后将下面的代码粘贴进"Program" 类:
SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;Initial Catalog=ProductDB;Integrated Security=SSPI;");
using (ProductDBContext context = ContextBuilder.Create<ProductDBContext>(connection))
{
if (!context.DatabaseExists())
context.CreateDatabase();
Category food = new Category { CID = 1, Name = "Food" };
Product bovril = new Product { ID = 1, Name = "Bovril" };
Product marmite = new Product { ID = 2, Name = "Marmite" };
Product vegemite = new Product { ID = 3, Name = "Vegemite" };
food.Products.Add(bovril);
food.Products.Add(marmite);
food.Products.Add(vegemite);
context.Categories.AddObject(food);
context.SaveChanges();
// Query the database
food = context.Categories.Single();
foreach (var product in food.Products)
Console.WriteLine(product.Name);
}
上面的代码按约定创建了一个上下文,连向本地安装的SQLExpress中的ProductDB数据库。如果ProductDB数据库还不存在,就创建该数据库。
最后,在上下文开始运行后,你就象平常一样使用它,在这个例子中,我们创建了一个Category实例,三个Product实例,两者互相关联,然后我们从数据库中获取Category对象,然后使用LazyLoading(即DeferredLoading),对它的产品进行循环。
就是这么简单!
11) 配置ContextBuilder
迄今为止,我们是按约定来做一切的,因为Code Only可以按约定推断出任何东西。但如果我们将Category类改成象这样的话:
public class Category
{
private List<Product> _products;
public int CID { get; set; }
public string Name { get; set; }
public virtual List<Product> Products {
get
{
if (_products == null)
_products = new List<Product>();
return _products;
}
set
{
_products = value;
}
}
}
CodeOnly不知道CID是键(key)【见注】,这意味着你需要创建一个ContextBuilder实例,用它来将CID注册成键,象这样:
var builder = new ContextBuilder<ProductDBContext>();
builder.RegisterKey((Category c) => c.CID);
如果需要的话,你可以在同个Builder上注册许多个键,你配置完你的Builder之后,你可以使用它的Create方法来创建一个ProductDBContext实例:
using (ProductDBContext context = builder.Create(connection))
其它的代码没变。
一般来说,在需要创建ObjectContext时,你应该重用你配置的ContextBuilder,而不是每次都重新配置,这会对性能有帮助。最好的做法大概是通过一个静态变量来做。
【注】按约定,任何叫ID, Id, ClassNameID 或 ClassNameId的属性会被假定为实体键。如果找不到这些名称的属性的话,那么你需要调用RegisterKey(),来告诉Entity Framework哪个属性是键。
Beta1版的CTP中Code Only功能的已知限制:
这个版本是一个非常早期的Code Only预览版,因此它有许多已知的限制,我们计划在以后的版本中解决它们,这些限制包括:
- Alex James
Entity Framework的Program Manager