zoukankan      html  css  js  c++  java
  • 架构模式对象与关系结构模式之:标识域(Identity Field)

    一:标识域(Identity Field)

    标识域(Identity Field)可以理解为主键。使用领域模型和行数据入口的时候,就要使用标识域,因为这两个对象代表的是唯一存在的那个数据记录。事务脚本、表模块、表数据入口等就不需要这个映射。

    public abstract class DomainObj
    {
        public string Id {get; set;}

        public string Name {get; set;}
        protected UnitOfWork uow = new UnitOfWork();
        protected void MakeNew()
        {
            uow.RegisterNew(this);
        }
        protected void MakeDirty()
        {
            uow.RegisterDirty(this);
        }
        protected void MakeRemoved()
        {
            uow.RegisterRemoved(this);
        }
    }

    二:外键映射(Foreign Key Mapping)

    所谓 外键映射 就是在获取对象的时候,把对象中的属性对象的值也获取到。我们在 延迟加载 中,使用的就是这一技术。这是 UserMap 中的一段代码,显示了如何将 组织 和 用户 以及用户所在的班级集合(一个用户可能存在于多个班级中) 一起进行获取到:

    public override User AbstractFind(string id)
    {
        var user = base.AbstractFind(id);
        if( user == null )
        {
            //
            string sql = @"
            DECLARE @ORGID VARCHAR(32)='', @TRAINNINGS VARCHAR(MAX)='';
            SELECT @ORGID=OrganizationId,@TRAINNINGS=TrainingIds FROM [EL_Organization].[USER] WHERE ID=@Id
            SELECT * FROM [EL_Organization].[USER] WHERE ID=@Id
            SELECT * FROM [EL_Organization].[ORGANIZATION] WHERE ID=@ORGID
            SELECT * FROM [EL_Organization].[Training] WHERE CHARINDEX(ID + ',', @TRAINNINGS + ',') > 0";
            var pms = new SqlParameter[]
            {
                new SqlParameter("@Id", id)
            };
            var ds = SqlHelper.ExecuteDataset(CommandType.Text, sql, pms);
            user = DataTableHelper.ToList<User>(ds.Tables[0]).FirstOrDefault();
            user.Organization =  DataTableHelper.ToList<Organization>(ds.Tables[1]).FirstOrDefault();
            user.Trainnings =  DataTableHelper.ToList<Trainning>(ds.Tables[2]).ToList();
            if(user == null)
            {
                return null;
            }

            user = Load(user);
            // 注意,除了 Load User 还需要 Load Organization
            user.Organization = Load(user.Organization) as Organization;
            foreach(var t in user.Trainnings)
            {
                Load(t);
            }
            return user;
        }
        return user;
    }

    三:依赖映射(Dependent Mapping)

    依赖映射的表现形式就是:依赖着本身没有数据映射器,其所有操作数据库的行为都发生在所有者中间。

    依赖者没有标识域(当然,这并不意味着数据库中它就一定没有主键)。依赖者与值对象很像,或者说,从 C# 的语法的角度而言,它们没有区别。

    四:嵌入值(Embedded Value)

    指领域模型中用到的那些小对象,它们对数据库没有意义,对领域对象却有意义。

    五:升级版的标识映射

    如果表示映射不是仅仅一个字段该怎么办,我们需要考虑多个字段,下面是一个标识映射的升级版本,查看:

    public class Key : IEquatable<Key>
    {
        private object[] fields;

        private string domainType;

        public Key(string id, Type type)
            : this(new[] { id }, type.ToString())
        {

        }

        public Key(object[] fields, string domainType)
        {
            if (string.IsNullOrEmpty(domainType))
                throw new ArgumentNullException("domainType can not be null");

            CheckKeyNotNull(fields);
            this.fields = fields;
            this.domainType = domainType;
        }

        private void CheckKeyNotNull(object[] fields)
        {
            if (fields == null)
            {
                throw new ArgumentNullException("Can not have a null key");
            }

            foreach (var field in fields)
            {
                if (field == null)
                {
                    throw new ArgumentNullException("Can not have a null element of key");
                }
            }
        }

        private void CheckSingleKey()
        {
            if (fields.Length > 1)
            {
                throw new ArgumentException("Can not take value on composite key");
            }
        }

        public string GetId()
        {
            CheckSingleKey();
            return fields[0].ToString();
        }

        public override bool Equals(object obj)
        {
            if (obj == null) return false;
            if (object.ReferenceEquals(this, obj)) return true;
            if (this.GetType() != obj.GetType()) return false;
            return Equals(obj as Key);
        }

        public bool Equals(Key other)
        {
            if (this.fields.Length != other.fields.Length)
            {
                return false;
            }

            for (int i = 0; i < fields.Length; i++)
            {
                if (!fields[i].Equals(other.fields[i]))
                {
                    return false;
                }
            }

            if (this.domainType != other.domainType)
            {
                return false;
            }

            return true;
        }

        public override int GetHashCode()
        {
            int hash = 0;

            for (int i = 0; i < fields.Length; i++)
            {
                hash += fields[i].GetHashCode();
            }

            hash += this.domainType.GetHashCode();
            return hash;
        }
    }

    代码不再多议。

  • 相关阅读:
    CMP指令(转)
    步进电机简介
    IDE改为AHCI后系统无法启动的解决办法
    无线网络(WLAN)常见加密方式介绍
    51单片机学习记录——数码管动态显示
    DEDECMS 调用上级栏目标题
    微信小程序开发系列(二)小程序的全局文件
    微信小程序开发系列(一)小程序开发初体验
    python+unittest日志和报告输出模块
    pip更换国内镜像源
  • 原文地址:https://www.cnblogs.com/luminji/p/3735335.html
Copyright © 2011-2022 走看看