• 【转】【翻译】Entity Framework 特性CTP全程示范: Code Only


    【原文地址】Feature CTP Walkthrough: Code Only for the Entity Framework
    【原文发表日期】 22 June 09 02:54 PM

    【译 注】.NET 3.5 SP1中的Entity Framework着重于“数据库优先(Database First)”,即从数据库中逆工程生成实体数据模型。而Visual Studio 2010/.NET 4.0中的Entity Framework 4.0引进了“模型优先(Model First)”,即允许你先生成实体数据模型,然后生成映射到该模型的数据库。而Entity Framework Feature CTP1版则更进一步,推出了“只用代码(Code Only)”的预览版,不再需要EDMX文件。 相关的想法请参考这个贴子。你需要下列软件才能运行这个示范:
    1. Visual Studio 2010 Beta 1
    2. Entity Framework Feature CTP1 (同时参考Entity Framework Feature CTP 1一文,如果你对该CTP中其他特性,特别是POCO模板等,感兴趣的话)
    3. 本地的SQL Server 2008 Express或者SQL Server

    Code Only全程示范

    1) 创建一个名叫“"CodeOnlyWalkthru"”的控制台应用:

    blog1

    2) 往"CodeOnlyWalkThru"解决方案中加一个新的项目:

    blog1

    3) 选择“类库”,将其命名为"Entities":

    blog1

    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(生成类)":

    blog1

    在新的Product类中,粘贴入下面这些代码:

    public class Product
    {
    public int ID { get; set; }
    public string Name { get; set; }
    }

    至此,你的项目应该象这样:

    blog1

    我们把这些实体类放进了一个单独的项目,这样它们会被编译进一个对Entity Framework无依赖的程序集中。因此,Entities程序集对持久性是透明的,这对一些开发人员来说,是非常重要的。对持久性有意识的代码存在于 另外的程序集中,引用对持久性是透明的程序集。

    6) 在"CodeOnlyWalkThru"项目中,添加对Entities项目的引用:

    blog1

    7) 在"CodeOnlyWalkThru"项目中,添加对"System.Data.Entity" 和 "Microsoft.Data.Entity.Ctp"的引用:

    blog1

    image

    注: 从长远看来,我们计划将“Code Only”的功能并入核心的Entity Framework程序集。之后,你就只需第一个引用。

    8) 在"CodeOnlyWalkThru" 项目中,加一个新的叫"ProductDBContext"的类:

    blog1

    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预览版,因此它有许多已知的限制,我们计划在以后的版本中解决它们,这些限制包括:

    • 不支持复杂类型(ComplexType)
    • 不支持可配置的映射
    • 只支持Table per Hierarchy继承策略
    • 不支持Facet的指定,譬如,你无法指定数据库中一个字符串字段的最大长度,而只用默认值
    • 没有提供器模型(Provider Model),所以CodeOnly 目前只支持SqlServer
    • CodeOnly没有提供方式让你指定哪个属性参与了同个关系,但只是对方的倒转(inverse)。譬如,如果在上面的例子中,你往 Product类中加了一个Category属性, 结果在Product和Category间,会有2个关系,因此在Products表中会生成2个外键,因为Entity Framework无法推断Product.Category和Category.Products只是对方的倒转。
    • 不支持多对多关系

    - Alex James
    Entity Framework的Program Manager



    推荐文章
  • 相关阅读:
    经典算法之冒泡排序(Bubble Sort)-Python实现
    经典算法之快速排序(Quick Sort)-Python实现
    2020年SRE的随心感悟
    django: 像正常运行django的项目运行单个文件
    整理一下javascript中offsetWidth、clientWidth、width、scrollWidth、clientX、screenX、offsetX、pageX的具体含义
    requestAnimationFram 的优势及使用场景
    js 隐式数据转换带来的BUG
    为什么我不建议在js中使用链接变量分配
    关于JS函数传参的数据修改
    实现一个查看浏览器内核及版本号的功能函数
  • 原文地址:https://www.cnblogs.com/fcsh820/p/1866354.html
Copyright © 2020-2023  润新知