架构模式对象与关系结构模式之:标识域(Identity Field)

简介: 一:标识域(Identity Field) 标识域(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;
    }
}

代码不再多议。

Creative Commons License本文基于 Creative Commons Attribution 2.5 China Mainland License发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 http://www.cnblogs.com/luminji(包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
目录
相关文章
|
13天前
|
存储
域对象
域对象:ServletContext l void setAttribute(String name, Object value):存储属性; l Object getAttribute(String name):获取属性; l void removeAttribute(String name):移除属性; l Enumeration getAttributeNames():获取所有属性名称;
|
1月前
|
Python
通过 type 和 object 之间的关联,进一步分析类型对象
通过 type 和 object 之间的关联,进一步分析类型对象
56 3
|
安全
RxSwift特征序列Driver的使用,以及共享附加作用与非共享附加作用的区别?
RxSwift特征序列Driver的使用,以及共享附加作用与非共享附加作用的区别?
175 0
|
存储 BI 数据库
access各对象之间的关系
access各对象之间的关系
|
存储 编译器 C语言
C++ 基础篇之类 & 对象的关系
C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。
|
数据库
一对多关系domain Model中设置使用AutoMapper时出错
一对多关系domain Model中设置使用AutoMapper时出错
171 0
一对多关系domain Model中设置使用AutoMapper时出错
|
XML 数据格式 开发者
定义实体|学习笔记
快速学习定义实体
153 0
Focusable 属性和IsTabStop 属性之间的关系
原文:Focusable 属性和IsTabStop 属性之间的关系 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Libby1984/article/details/54881460 控件的Focusable 属性确定控件是否允许接收键盘输入焦点,控件的 IsTabStop 属性确定是否允许通过Tab键导航到控件。
1097 0
下一篇
无影云桌面