zoukankan      html  css  js  c++  java
  • LLBL Gen + Entity Framework 程序设计入门

    Entity Framework推出有好几年,除了微软的Visual Studio可以做实体框架开发外,第三方的开发工具如LLBL Gen,

    Devart Entity Developer也可以用来做设计开发。

    设计数据库表Configuration,它的SQL定义如下

    IF OBJECT_ID ('dbo.Configuration') IS NOT NULL
        DROP TABLE dbo.Configuration
    GO
    
    CREATE TABLE dbo.Configuration
        (
        Recnum      INT IDENTITY NOT NULL,
        MasterKey   NVARCHAR (50) NOT NULL,
        Description TEXT NULL,
        Remark      NVARCHAR (400) NULL,
        CONSTRAINT PK_X_Config PRIMARY KEY (MasterKey)
        )
    GO

    打开LLBL Gen,创建一个新项目,选择Entity Framework v1

    image

    这里还有其它版本的Entity Framework。对应关系如下

    Entity Framework v1 =>  Entity Framework 3.5 SP1

    Entity Framework v4 => Entity Framework 4/4.5

    再到Category Explorer窗口中,选择添加数据库映射,选择数据库类型,设置连接参数

    image

    生成实体模型,继续在Category Explorer窗口中,把表添加到当前项目的实体中,如下图所示

    image

    验证实体类型,准备生成代码,但是出现以下几个错误:

    The Entity "FileType" contains field "FileType" which has the same name as its containing element,something which isn't supported by the Entity Framework

    映射的实体名字段中,不能包含与实体名称一样的字段。比如,我有一个FileType的表,映射到FileType实体,它包含一个FileType的主键字段,自动生成映射时,这是不允许的。

    清除这个错误之后,按F7生成代码,用Visual Studio 2012打开项目,如下图所示

    image

    LLBL Gen代码生成器帮忙我们生成Entity Framework所需要的edmx文件,类型定义和DataContext类型。

    来看一下生成的类型定义代码,Configuration表映射的实体类型Configuration实体,它的代码如下

    /// <summary>Class which represents the entity 'Configuration'.</summary>
        [Serializable]
        [DataContract(IsReference=true)]
        [EdmEntityType(NamespaceName="Entity35Model", Name="Configuration")]
        public partial class Configuration : CommonEntityBase
        {
            #region Class Member Declarations
            private System.String _description;
            private System.String _masterKey;
            private System.Int32 _recnum;
            private System.String _remark;
            #endregion
            
            #region Extensibility Method Definitions
            partial void OnDescriptionChanging(System.String value);
            partial void OnDescriptionChanged();
            partial void OnMasterKeyChanging(System.String value);
            partial void OnMasterKeyChanged();
            partial void OnRecnumChanging(System.Int32 value);
            partial void OnRecnumChanged();
            partial void OnRemarkChanging(System.String value);
            partial void OnRemarkChanged();
            #endregion
                    
            /// <summary>Initializes a new instance of the <see cref="Configuration"/> class.</summary>
            public Configuration() : base()
            {
            }
    
            /// <summary>Factory method to create a new instance of the entity type 'Configuration'</summary>
            /// <param name="masterKeyValue">The initial value for the field 'MasterKey'</param>    
            /// <param name="recnumValue">The initial value for the field 'Recnum'</param>    
            public static Configuration CreateConfiguration(System.String masterKeyValue, System.Int32 recnumValue)
            {
                var toReturn = new Configuration();
                toReturn.MasterKey = masterKeyValue;
                toReturn.Recnum = recnumValue;
                return toReturn;
            }
    
            #region Class Property Declarations
            /// <summary>Gets or sets the Description field. </summary>
            [DataMember]
            [EdmScalarProperty()]
            public System.String Description
            {
                get    { return _description; }
                set
                {
                    OnDescriptionChanging(value);
                    this.ReportPropertyChanging("Description");
                    _description = SetValidValue(value, true);
                    this.ReportPropertyChanged("Description");
                    OnDescriptionChanged();
                }
            }
            
            /// <summary>Gets or sets the MasterKey field. </summary>
            [DataMember]
            [EdmScalarProperty(EntityKeyProperty=true, IsNullable=false)]
            public System.String MasterKey
            {
                get    { return _masterKey; }
                set
                {
                    if(_masterKey==value)
                    {
                        return;
                    }
                    OnMasterKeyChanging(value);
                    this.ReportPropertyChanging("MasterKey");
                    _masterKey = SetValidValue(value, false);
                    this.ReportPropertyChanged("MasterKey");
                    OnMasterKeyChanged();
                }
            }
            
            /// <summary>Gets or sets the Recnum field. </summary>
            [DataMember]
            [EdmScalarProperty(IsNullable=false)]
            public System.Int32 Recnum
            {
                get    { return _recnum; }
                private set
                {
                    OnRecnumChanging(value);
                    this.ReportPropertyChanging("Recnum");
                    _recnum = SetValidValue(value);
                    this.ReportPropertyChanged("Recnum");
                    OnRecnumChanged();
                }
            }
            
            /// <summary>Gets or sets the Remark field. </summary>
            [DataMember]
            [EdmScalarProperty()]
            public System.String Remark
            {
                get    { return _remark; }
                set
                {
                    OnRemarkChanging(value);
                    this.ReportPropertyChanging("Remark");
                    _remark = SetValidValue(value, true);
                    this.ReportPropertyChanged("Remark");
                    OnRemarkChanged();
                }
            }
            
            #endregion
        }

    LLBL Gen让生成的实体类型派生于CommonEntityBase,这个类型派生于EntityObject,定义如下

    /// <summary>Class which is the common base class for all generated entity classes.</summary>
    /// <remarks>As all non-subtype entity classes derive from this class, use a partial class of this class to implement code which is shared among all generated entity classes</remarks>
        [DataContract(IsReference = true)]
        [Serializable]
        public abstract partial class CommonEntityBase : EntityObject
        {
            #region Class Extensibility Methods
            /// <summary>Method called from the constructor</summary>
            partial void OnCreated();
            #endregion
            
            /// <summary>Initializes a new instance of the <see cref="CommonEntityBase"/> class.</summary>
            protected CommonEntityBase() : base()
            {
                OnCreated();
            }
    
        }

    可以在这个类型中,创建一些公共的方法以方便在生成的实体类型中使用。

    LLBL Gen为实体框架的实体的每个属性添加了二个跟踪机制方法:Changing和Changed方法。这里可以写我们实体的业务逻辑。比如在采购单中,用户改变单价时,自动重新计算金额(金额=数量*单价)。

    以备注属性为例子,请看下面的代码

    /// <summary>Gets or sets the Remark field. </summary>
    [DataMember]
    [EdmScalarProperty()]
    public System.String Remark
    {
                get    { return _remark; }
                set
                {
                    OnRemarkChanging(value);
                    this.ReportPropertyChanging("Remark");
                    _remark = SetValidValue(value, true);
                    this.ReportPropertyChanged("Remark");
                    OnRemarkChanged();
                }
    }
    partial void OnRemarkChanging(System.String value);
    partial void OnRemarkChanged();
     

    这二个方法都是partial方法,如果我们没有定义方法体,则编译时,它会被忽略。partial方法是C# 3.0才引入的特性,为方便代码生成器与开发人员之间的合作更紧密。试想一下,怎么在不修改代码生成器生成的方法的情况下,添加自定义的业务代码到类型的方法,属性中去呢?答案是partial方法。

    同时,因为生成的实体类型已经加了partial关键字,所以我们可以再加入一个同名的实体类型,用来写业务逻辑,而不更改代码生成器自动生成的代码。

    最后,写一个测试方法,让它读取系统的配置表Configuration中的数据:

    public static void Main(string[] args)
     {
                Entity35DataContext entity35DataContext = new Entity35DataContext();
                var configurations = from item in entity35DataContext.Configurations
                               select item;
    
                foreach (var dbDataRecord in configurations)
                {
                    string companyCode = dbDataRecord.MasterKey;
    
                }
    }
     

    一行代码即可完成数据库的读取,而且读取的数据是强类型,非常方便。

    一般在入门例子中,容易出错的地方是配置文件的内容,来看一下App.config文件的内容:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <connectionStrings>
            <!-- please adjust the connection string embedded in the element below to target the proper catalog / server using the proper user / password combination -->
            <add name="ConnectionString.SQL Server (SqlClient)" connectionString="metadata=res://*/Entity35.csdl|res://*/Entity35.ssdl|res://*/Entity35.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.sqlexpress;initial catalog=Framework;integrated security=SSPI;persist security info=False;packet size=4096&quot;" providerName="System.Data.EntityClient" />
        </connectionStrings>
    </configuration> 

    这里是设置连接字符串的地方,从生成的ObjectContext类型中,可以看到不带参数的构造方法为从这里读取连接字符串,它的其它的几个方法,如下代码所示

    /// <summary>Initializes a new instance of the <see cref="Entity35DataContext"/> class using the connection string found in the 'Entity35' section of the application configuration file.</summary>
    public Entity35DataContext() : base("name=ConnectionString.SQL Server (SqlClient)", "Entity35Entities")
    {
                Initialize();
    }
            
    /// <summary>Initializes a new instance of the <see cref="Entity35DataContext"/> class</summary>
    public Entity35DataContext(string connectionString) : base(connectionString, "Entity35Entities")
    {
                Initialize();
    }
            
    /// <summary>Initializes a new instance of the <see cref="Entity35DataContext"/> class</summary>
    /// <param name="connection">Ready to use EntityConnection object to be used with this context</param>
    public Entity35DataContext(System.Data.EntityClient.EntityConnection connection) : base(connection, "Entity35Entities")
    {
                Initialize();
    }
     
     

    Entity Framework的连接字符串与经常写的SQL Server的SqlConnection的字符串有所区别,要指定依据edmx生成的三个文件的位置,因为edmx文件的Build Action为EntityDeploy,所以它会被嵌入到生成的程序集中。

    image

    用.NET Reflector载入生成的实体程序集,查看它的资源文件,如上图所示,三个资源文件被嵌入在程序集中。

     

  • 相关阅读:
    Echarts markPoint 动态数据添加,选择性查询
    echarts timeline点击以后 蓝色的checkpoint位置不跟当前点击的节点重合
    Echarts 动态添加到map显示
    tomcat 下不在tomcat发布项目,引用外部链接
    SQL Server 2008安装
    eclipce 安装 svn插件(百度知道)
    迅为IMX6ULL开发板Linux蜂鸣器实验
    4412开发板-Android4.4典型功能相关源码修改及定制
    IMX6ULL开发平台Linux-LED实验
    迅为iTOP4418开发板运行Android7.1/Qt5.7/Ubuntu12.04系统源码开源
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/3204714.html
Copyright © 2011-2022 走看看