zoukankan      html  css  js  c++  java
  • Entity Framework 4 POCO

    Entity Framework 4 第一篇 POCO

    EFv1版本中,并没有提供对POCOPlain Old CLR Objects)的支持。目前,在.Net4.0 Beta2中的EF 4完善了很多。可以预见,正式的EF4版本应该会有很多改进和完善。在EF4中的提供了对POCO的支持。并支持的数据定义语言(DDL)。这样,我们可以不需要事先生成EDMX文件,而是通过代码编程来实现对数据的操作(Code Only)。

    下面,介绍在EF4中利用POCO来实现数据定义操作。

    0步:准备工作:

    操作系统:Windows 7旗舰版

    开发环境:VS2010 Beta2+SQL Server2008

    1步:先建立需要的数据模型类。

    例如:我们分别建立PersonCompany两个POCO数据模型,以便对应数据库中的PersonCompany表,代码如下:

    /// <summary>

        /// 对应数据库中的Person表

        /// </summary>

        public class Person

        {

            public string IdentityNo { get; set; }

            public string Name { get; set; }

            public int Age { get; set; }

            public string Phone { get; set; }

            public Company Company { get; set; }

            public string Position { get; set; }

        }

     

    /// <summary>

        /// 对应数据库中的Company表

        /// </summary>

        public class Company

        {

            public int CompanyId { get; set; }

            public string CompanyName { get; set; }

            public string Province { get; set; }

            public string City { get; set; }

            public string Address { get; set; }

            public string HomePage { get; set; }

            public string Phone { get; set; }

        }

    2步:创建上下文访问类

    因为此时是没有EMDX文件的。所以,建立我们需要创建一个继承自ObjectContext的上下文访问类,用描述及访问我们之前定义的数据模型。代码如下:

    public class POCOContext : ObjectContext

        {

            public POCOContext(EntityConnection conn) : base(conn) { }

            public ObjectSet<Person> Persons

            {

                get

                {

                    return base.CreateObjectSet<Person>();

                }

            }

            public ObjectSet<Company> Companies

            {

                get

                {

                    return base.CreateObjectSet<Company>();

                }

            }

        }

    3步:代码实现

    接着,我们就只需要通过创建一个POCOContext上下文,以便来完成我们的数据库操作就可以了。代码如下:

    [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>();//创建上下文

                builder.Entity<Person>().HasKey(p => p.IdentityNo);//设置表的主键为IdentityNo字段

                builder.Entity<Company>().HasKey(c => c.CompanyId);//设置表的主键为CompanyId字段

                POCOContext context = builder.Create(con);

                if (!context.DatabaseExists())

                    context.CreateDatabase();//创建数据库

              }

    最后,运行上面的测试,就会自动创建一个名为NewNorthwind的数据库,并包含PersonCompany两张表。如下图所示:

     

    EF4中,ObjectContext扩展更多的方法,如下:

    public static class ObjectContextExtensions

        {

            public static void CreateDatabase(this ObjectContext context);

            public static string CreateDatabaseScript(this ObjectContext context);

            public static bool DatabaseExists(this ObjectContext context);

            public static void DeleteDatabase(this ObjectContext context);

        }

    同时,EF4实体类也提供了更多的方法,如下:

    public class EntityConfiguration<TEntity> : StructuralTypeConfiguration<TEntity>

        {

            public EntityConfiguration();

            public EntityConfiguration<TEntity> HasKey<TKey>(Expression<Func<TEntity, TKey>> getKey);

            public HierarchyEntityMapGenerator<TEntity> MapHierarchy();

            public EntityMap MapHierarchy(Expression<Func<TEntity, object>> propertyMap);

            public EntityMap MapSingleType(Expression<Func<TEntity, object>> propertyMap);

            public NavigationPropertyConfiguration<TEntity, TRelated> Relationship<TRelated>(Expression<Func<TEntity, ICollection<TRelated>>> propertyExpression);

            public NavigationPropertyConfiguration<TEntity, TRelated> Relationship<TRelated>(Expression<Func<TEntity, TRelated>> propertyExpression);

            public RelationshipPropertyConfiguration<TEntity, TRelated> RelationshipFrom<TRelated>(Expression<Func<TRelated, ICollection<TEntity>>> propertyExpression);

            public RelationshipPropertyConfiguration<TEntity, TRelated> RelationshipFrom<TRelated>(Expression<Func<TRelated, TEntity>> propertyExpression);

        }

    这样,通过这些扩展的方法,我们可以只通过代码编程的方式(Code Only)对数据库以及数据库中各个表间的关系进行操作。

    个人觉得,与.Net3.5 SP1中的EF v1版相比,的确是很大的改进,感觉越来越像NHibernate了。相信在未来正式发布的.Net4.0中,EF4应该会更加完善了。

     

    本篇,继续介绍关于EF 4中的POCO有关数据定义(DDL)方面的东西,比如:指定主键,设置字段长度,指定浮点字段的精度,设置关系,约束,延迟加载等内容。相比EFV1来说,EF 4的确改进了不少。

    0步,准备工作:

    需要的环境:Windows 7+VS2010beta2+EF4CTP2+SQL SERVER2008

    1步,建立数据模型类。例如,我们分别写了CompanyPerson两个类文件。为方便查看各种类型(如: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; }

        }

    CompanyPOCO类文件中,我们使用了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文件包含所有表的描述、定义、映射,手动修改起来很是不方便。这样相比之下,写代码实现看上去的确是清爽了不少。但是,如果表比较多,表间关系比较复杂的话,估计写代码也容易弄混了。

  • 相关阅读:
    tolua总结(二)
    convirt管理端离线安装
    c++运用backtrace追踪函数调用的堆栈
    不知道自己适不适合作程序员
    这次六级又没过
    我也有blog了,呵呵!
    代理 XP”组件已作为此服务器安全配置的一部分被关闭。系统管理员可以使用 sp_configure 来启用“代理 XP”。
    SQLServer中的GROUPING,ROLLUP和CUBE
    android studio ndk 环境配置成eclipse模式
    寄存器小记
  • 原文地址:https://www.cnblogs.com/dudu837/p/1900505.html
Copyright © 2011-2022 走看看