zoukankan      html  css  js  c++  java
  • 二、打造实体基类

    二、打造实体基类

     关系型数据表中一般有共性的部分是所有的实体都有ID(但ID的类型不一样),很多业务表都有主从的关系。

    2.1表定义

    比如下面的表

    City定义

    CREATE TABLE [lt_dictionary].[City](

        [CityID] [int] IDENTITY(1,1) NOT NULL,

        [Name] [nvarchar](50) NOT NULL,

        [PostalCode] [dbo].[PostalCodeType] NOT NULL,

        [DistanceCode] [nvarchar](5) NOT NULL,

        [Province] [nvarchar](3) NOT NULL,

        [Longitude] [decimal](5, 2) NOT NULL,

        [Latitude] [decimal](5, 2) NOT NULL,

        [Enable] [dbo].[EnableType] NOT NULL CONSTRAINT [DF_City_Enable] DEFAULT ((1)),

        [LastEditDate] [dbo].[BusinessDateType] NOT NULL CONSTRAINT [DF_City_LastEditDate] DEFAULT (getdate()),

        [UpdateDay] AS (datediff(day,[LastEditDate],getdate())),

        [Version] [timestamp] NOT NULL,

     CONSTRAINT [PK_City] PRIMARY KEY CLUSTERED

    (

        [CityID] ASC

    )

    这个城市表的IDint的。

    BusinessOrders定义

    CREATE TABLE [lt_business].[BusinessOrders](

        [BusinessOrderID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_BusinessOrders_BusinessOrderID] DEFAULT (newid()),

        [Number] [dbo].[BusinessOrderType] NOT NULL CONSTRAINT [DF_BusinessOrders_Number] DEFAULT ([dbo].[CreateBusinessOrderNumber]('Bz')),

        [Deadline] [dbo].[BusinessDateType] NOT NULL,

        [PaymentMethod] [nchar](2) NOT NULL,

        [PaymentEnterprise] [dbo].[DescriptionType] NOT NULL,

        [Origin] [dbo].[DescriptionType] NOT NULL,

        [Destination] [dbo].[DescriptionType] NOT NULL,

        [DeliveryType] [nchar](2) NOT NULL,

        [Level] [dbo].[LevelType] NOT NULL,

        [Remark] [dbo].[DescriptionType] NOT NULL,

        [Indicator] [nvarchar](3) NOT NULL,

        [FreightPayable] [dbo].[DescriptionType] NOT NULL,

        [WarehouseID] [int] NOT NULL,

        [OrderID] [uniqueidentifier] NOT NULL,

        [BusinessDate] [dbo].[BusinessDateType] NOT NULL CONSTRAINT [DF_BusinessOrders_BusinessDate] DEFAULT (getdate()),

        [StaffID] [int] NOT NULL,

        [Version] [timestamp] NOT NULL,

        [State] AS ([dbo].[GetBusinessOrderState]([BusinessOrderID])),

     CONSTRAINT [PK_BusinessOrders] PRIMARY KEY CLUSTERED

    BusinessOrdersIDuniqueidentifier类型。

    BusinessOrderDetaileds定义

    CREATE TABLE [lt_business].[BusinessOrderDetaileds](

        [BusinessOrderDetailedID] [uniqueidentifier] NOT NULL CONSTRAINT [DF_BusinessOrderDetaileds_BusinessOrderDetailedID] DEFAULT (newid()),

        [BusinessOrderID] [uniqueidentifier] NOT NULL,

        [Serial] [int] NOT NULL,

        [GoodsDescription] [dbo].[DescriptionType] NOT NULL,

        [Packing] [nvarchar](2) NOT NULL,

        [Quantity] [decimal](18, 2) NOT NULL,

        [TotalPackages] [decimal](18, 2) NOT NULL,

        [Weight] [decimal](18, 2) NOT NULL,

        [Measurement] [decimal](18, 2) NOT NULL,

        [Version] [timestamp] NOT NULL,

        [State] AS ([dbo].[GetBusinessOrderItmeState]([BusinessOrderDetailedID])),

        [CompleteQuantity] AS ([dbo].[GetBusinessOrderItmeCompleteQuantity]([BusinessOrderDetailedID])),

     CONSTRAINT [PK_BusinessOrderDetaileds] PRIMARY KEY CLUSTERED

    BusinessOrderDetailedsIDuniqueidentifier类型,其外键对应的是BusinessOrders实体的ID

    2.2关于实体基类定义的要求

    我希望有这个的实体基类,该实体定义了所有的继承者(实体的具体实现类)都必须有ID属性,但ID属性的数据类型由各实体自己定义。我还希望,能在类的定义上看出有主从表的关系,并且能约束主从表的一些行为。而且我还希望基类能自动的实现对属性的赋值。

    2.3定义EntityBase

    EntityBase定义(继承部分)

    [Serializable]

    public abstract class EntityBase<T,ID> where T : EntityBase<T,ID>

    {

     

        /// <summary>

        /// 所有的实体都必须有一个唯一标识,具体类型有实体各自实现

        /// </summary>

        [System.ComponentModel.DataObjectField(true, true, false)]

        public virtual ID Identity

        {

            set;

            get;

        }

    }

    EntityBase定义了一个ID的泛型,该泛型描述了继承者必须实现具体的ID类型。

    2.4定义EntityBaseUndo功能

    在没有泛型的年代时,基类无了解子类的类型,因此基类只能实现一些返回或参数是基本数据类型的方法,如果要为子类提供个性化的方法,基类只能以object对象返回,且要求子类实现数据类型的强制转换。但现在,EntityBase还提供了一个T类型,因此我们可以实现Undo的功能。

    EntityBaseUndo部分)

    /// <summary>

    /// 实体是否支持撤销

    /// </summary>

    public abstract bool HasUndo

    {

        get;

    }

     

    /// <summary>

    /// 还可以撤销的次数

    /// </summary>

    public int UndoCount

    {

        get

        {

            return undoStack.Count;

        }

    }

     

    /// <summary>

    /// 得到实体的副本

    /// </summary>

    /// <returns></returns>

    protected virtual T Clone()

    {

        return (T)this.MemberwiseClone();

    }

     

    /// <summary>

    /// 将复本入栈

    /// </summary>

    protected void Push()

    {

        if (this.HasUndo)

        {

            this.Push((T)this.Clone());

        }

    }

     

    /// <summary>

    /// 将复本入栈

    /// </summary>

    /// <param name="obj"></param>

    private void Push(T obj)

    {

        if (this.HasUndo)

        {

            undoStack.Push(obj.Clone());

        }

    }

     

    private System.Collections.Generic.Stack<T> undoStack = new Stack<T>();

     

    /// <summary>

    /// 将复本出栈

    /// </summary>

    /// <returns></returns>

    private T Pop()

    {

        if (undoStack.Count > 0)

        {

            return undoStack.Pop();

        }

        else

        {

            return null;

        }

    }

    /// <summary>

    /// 撤销

    /// </summary>

    /// <returns></returns>

    public T Undo()

    {

        return Pop();

    }

    使用了泛型,我们在类的内部提供了泛型队列,然后返回值和参数值都是泛型T,该T将由各个子类来具体实现。

    2.5定义EntityBase的数据访问能力

    /// <summary>

    /// 根据给定的连接字符串构造数据提供者

    /// </summary>

    /// <param name="connStr"></param>

    /// <returns></returns>

    protected static DataProviders.IDataProvider CreateDataProvider(string connStr)

    {

        return new DataProviders.SqlDataProvider.SqlDataProvider(connStr);

    }

    2.6定义EntityBase的构造函数

    EntityBase有一个接受System.Data.DataTable的构造函数,该构造函数将table中指定行的数据和本类的属性作对比,如果名称和数据类型匹配,则自动赋值。

    EntityBase构造函数

    /// <summary>

    /// 按table的指定行数据进行属性的初始化

    /// </summary>

    /// <param name="table"></param>

    /// <param name="indexRow"></param>

    public EntityBase(System.Data.DataTable table, int indexRow)

    {

        //遍历table中的每一列

        for (int i = 0; i <= table.Columns.Count - 1; i++)

        {

            //按列的名称,试图从当前对象中获取同名属性

     

            System.Reflection.PropertyInfo pinfo = this.GetType().GetProperty(table.Columns[i].ColumnName);

            if (pinfo != null)

            {//如果存在该属性

     

                object value = table.Rows[indexRow][table.Columns[i].ColumnName];//提取列的当前行值

     

                if (pinfo.PropertyType == table.Columns[i].DataType)//如果对象属性定义的类型和table的列的类型一致

                {

     

                    pinfo.SetValue(this, value, null);//赋值

                }

                else

                {

                    if (pinfo.PropertyType.IsEnum)//如果对象属性的值是枚举类型

                    {

     

                        if (value.GetType() == typeof(int))//数据库中保存的是int类型,则直接为枚举赋值

                        {

                            pinfo.SetValue(this, value, null);//赋值

                        }

                        if (value.GetType() == typeof(string))//如果数据库中保存的是string类型

                        {

                            pinfo.SetValue(this, Enum.Parse(pinfo.PropertyType, value.ToString(), false), null);//赋值

                        }

                    }

     

                    //如果对象的属性是Bitmap类型,对应的数据值是byte[]

                    if (pinfo.PropertyType==typeof(System.Drawing.Bitmap) && value.GetType()==typeof(byte[]))

                    {

                        pinfo.SetValue(this, new System.Drawing.Bitmap(new System.IO.MemoryStream((byte[])value)), null);//赋值

                    }

                }

            }

        }

    }

    2.7定义EntityBaseCreateInstance

    虽然EntityBase的构造函数有能力实现对属性的自动赋值,但我们可能要实例对象的集合或决定table中是否有值,应此我们需要实现CreateInstance方法。

    定义EntityBaseCreateInstances方法

    /// <summary>

    /// 通过table实例化一组对象

    /// </summary>

    /// <param name="table"></param>

    /// <returns></returns>

    public static List<T> CreateInstances(System.Data.DataTable table, int startRecord, int maxRecords)

    {

        List<T> instances = new List<T>();

     

        for (int i = startRecord; i <= maxRecords; i++)

        {

            instances.Add(CreateInstance(table, i));

        }

        return instances;

    }

     

    /// <summary>

    /// 通过table实例化一个对象

    /// </summary>

    /// <param name="table"></param>

    /// <param name="startRecord"></param>

    /// <param name="maxRecords"></param>

    /// <returns></returns>

    public static T CreateInstance(System.Data.DataTable table, int rowIndex)

    {

        if (table.Rows.Count > rowIndex)

        {

            return (T)System.Activator.CreateInstance(typeof(T), table, rowIndex);

        }

        else

        {

            return null;

        }

    }

     

    /// <summary>

    /// 默认按table的第一行实例化一个对象

    /// </summary>

    /// <param name="table"></param>

    /// <returns></returns>

    public static T CreateInstance(System.Data.DataTable table)

    {

        return CreateInstance(table, 0);

    }

     

     

    /// <summary>

    /// 通过table实例化一组对象

    /// </summary>

    /// <param name="table"></param>

    /// <param name="startRecord"></param>

    /// <returns></returns>

    public static List<T> CreateInstances(System.Data.DataTable table, int startRecord)

    {

        return CreateInstances(table, startRecord, table.Rows.Count - 1);

    }

     

    /// <summary>

    /// 通过table实例化一组对象

    /// </summary>

    /// <param name="table"></param>

    /// <returns></returns>

    public static List<T> CreateInstances(System.Data.DataTable table)

    {

        return CreateInstances(table, 0, table.Rows.Count - 1);

    }

  • 相关阅读:
    转载:configure生成的文件(1.5.3)《深入理解Nginx》(陶辉)
    现场管理
    02 表扫描
    01 成本的含义
    16 计划稳定性与控制
    14 事务处理
    13 SELECT 以外的内容
    12 索引
    11 半联结 & 反联结
    08 分析函数
  • 原文地址:https://www.cnblogs.com/shyleoking/p/1336675.html
Copyright © 2011-2022 走看看