而你的DTO数据对象的赋值进程就成了3个难题公海赌船网址,因为实人体模型型Entity的对象恐怕包蕴了别样实体的引用

再次来到目录

在选用Entity Framework
实体框架的时候,大家抢先11分之5时候操作的都以实体模型Entity,这些和数据库操作上下文结合,能够应用LINQ等各类便民花招,完结起来11分有益,一切看起来相当漂亮好。不过1旦怀念选取WCF的时候,大概就会超出繁多相关的圈套大概不当了。因为实人体模型型Entity的对象大概包含了别的实体的引用,在WCF里面就不能够展开系列化,出现谬误;而且根据WCF的时候,只怕无法有效使用Express表达式,不能直接利用LINQ等难点都一股脑出现了。本文基于上面的各样难题,演说了自笔者的总体Entity
Framework
实体框架的搞定思路,并且在里边引进了数额传输模型DTO来缓解难题,本文主要介绍数据传输模型DTO和实人体模型型Entity的告辞与1块,从而达成大家通畅、高效的WCF应用框架。

在运用Entity Framework
实体框架的时候,我们大部分时候操作的都是实人体模型型Entity,这一个和数据库操作上下文结合,能够动用LINQ等各类方便手腕,达成起来13分便利,壹切看起来非常美丽好。可是借使设想使用WCF的时候,或许就会遇上诸多有关的牢笼恐怕失实了。因为实体模型Entity的靶子也许包含了别样实体的引用,在WCF里面就不只怕举办种类化,出现错误;而且据他们说WCF的时候,恐怕不能够有效使用Express表达式,不可能直接使用LINQ等主题素材都1股脑出现了。本文基于上面包车型客车各种难点,演说了本人的全体Entity
Framework
实体框架的消除思路,并且在里面引进了数码传输模型DTO来消除难点,本文主要介绍数据传输模型DTO和实人体模型型Entity的握别与一齐,从而达成大家通畅、高效的WCF应用框架。

AutoMapper是3个.NET的靶子映射工具,壹般地,我们实行面向服务的支付时,都会涉及到DTO的概念,即数据传输对象,而为了减小系统的载荷,一般大家不会把整体表的字段作为传输的数码,而是单独根据现实处境,写2个新的类,这些类一般以DTO结尾,意思是说,它是互联网上的多寡传输用的,而你的DTO数据对象的赋值进程就成了三个题目,而为了减小赋值进度的代码量,AutoMapper就出来了,它可以兑现实业对实业的赋值进程,可能叫“映射进程”

1、实人体模型型Entity不可能在WCF中序列化

比如,大家定义的Entity Framework
实体类里面富含了别的对象的引用,例如有二个Role对象,有和其他表的关联关系的,暗中同意使用守旧艺术,在实体类里面增添[DataContract]方式。

/// <summary>
/// 角色
/// </summary>
[DataContract(IsReference = true)]
public class Role
{ 
    /// <summary>
    /// 默认构造函数(需要初始化属性的在此处理)
    /// </summary>
    public Role()
    {
        this.ID= System.Guid.NewGuid().ToString();

        //Children = new HashSet<Role>();
        //Users = new HashSet<User>();
     }

    #region Property Members

    [DataMember]
    public virtual string ID { get; set; }

    /// <summary>
    /// 角色名称
    /// </summary>
    [DataMember]
    public virtual string Name { get; set; }

    /// <summary>
    /// 父ID
    /// </summary>
    [DataMember]
    public virtual string ParentID { get; set; }

    [DataMember]
    public virtual ICollection<Role> Children { get; set; }

    [DataMember]
    public virtual Role Parent { get; set; }

    [DataMember]
    public virtual ICollection<User> Users { get; set; }

    #endregion

}

在WCF服务接口里面使用代码如下所示。

public class Service1 : IService1
{
    public List<Role> GetAllRoles()
    {
        return IFactory.Instance<IRoleBLL>().GetAll().ToList();
    }

     .........

那么大家在WCF里面使用的时候,会赢得下边包车型地铁唤醒。
接收对
http://localhost:11229/Service1.svc
的 HTTP 响应时发生错误。那或许是由于劳动终结点绑定未利用 HTTP
协议形成的。那还大概是出于服务器中止了 HTTP
请求上下文(可能由于劳动关闭)所致。有关详细新闻,请参见服务器日志。
暗许情状下,Entity
Framework为了帮助它的有的高等天性(延迟加载等),默许将自动生成代理类是设置为true。假若大家须要禁止自动生成代理类,那么能够在数据库操作上下文DbContext里面举行拍卖装置。

Configuration.ProxyCreationEnabled = false;

假定设置为false,那么WCF服务可以干活平常化,可是实体类对象里面包车型客车别样对象集合则为空了,也正是WCF没办法重返那么些引用的剧情。
并且,在Entity
Framework框架之中,那种把实体类贯穿各种层里面,也是一种不推荐的做法,由于WCF里面传输的数码都以种类号过的数码,也不知道该咋办像当地同样使用LINQ来兑现数量的处理操作的。
那么大家应该怎么着塑造基于WCF引用的Entity Framework实体框架呢?

一、实人体模型型Entity不能够在WCF中系列化

比如说,我们定义的Entity Framework
实体类里面富含了任何对象的引用,例如有三个Role对象,有和其它表的涉及关系的,默许使用古板办法,在实体类里面加多[DataContract]方式。

    /// <summary>
    /// 角色
    /// </summary>
    [DataContract(IsReference = true)]
    public class Role
    { 
        /// <summary>
        /// 默认构造函数(需要初始化属性的在此处理)
        /// </summary>
        public Role()
        {
            this.ID= System.Guid.NewGuid().ToString();

            //Children = new HashSet<Role>();
            //Users = new HashSet<User>();
         }

        #region Property Members

        [DataMember]
        public virtual string ID { get; set; }

        /// <summary>
        /// 角色名称
        /// </summary>
        [DataMember]
        public virtual string Name { get; set; }

        /// <summary>
        /// 父ID
        /// </summary>
        [DataMember]
        public virtual string ParentID { get; set; }

        [DataMember]
        public virtual ICollection<Role> Children { get; set; }

        [DataMember]
        public virtual Role Parent { get; set; }

        [DataMember]
        public virtual ICollection<User> Users { get; set; }

        #endregion

    }

在WCF服务接口里面使用代码如下所示。

    public class Service1 : IService1
    {
        public List<Role> GetAllRoles()
        {
            return IFactory.Instance<IRoleBLL>().GetAll().ToList();
        }

         .........

那正是说大家在WCF里面使用的时候,会取得下边包车型大巴唤起。

接收对 http://localhost:11229/Service1.svc
的 HTTP 响应时发生错误。那只怕是出于服务终结点绑定未采纳 HTTP
协议变成的。那还恐怕是出于服务器中止了 HTTP
请求上下文(恐怕由于劳动关闭)所致。有关详细音信,请参见服务器日志。

默许情形下,Entity
Framework为了扶助它的一对高端性子(延迟加载等),默许将自动生成代理类是设置为true。若是大家须求禁止自动生成代理类,那么可以在数据库操作上下文DbContext里面进行处理装置。

Configuration.ProxyCreationEnabled = false;

倘使设置为false,那么WCF服务能够干活平常化,不过实体类对象里面包车型客车其它对象集合则为空了,相当于WCF十分的小概重回这么些引用的始末。

与此同时,在Entity
Framework框架之中,那种把实体类贯穿各样层里面,也是1种不引入的做法,由于WCF里面传输的多少都以连串号过的多寡,也无能为力像本地同样使用LINQ来落到实处多少的拍卖操作的。

那正是说大家应当怎么塑造基于WCF引用的Entity
Framework实体框架呢?

自个儿心头的品类应该是那般的,用户业务服务,产品业务服务,订单业务服务,那样服务都使
用单独的数据库,它们之间的简报应用WCF实行落到实处,在获多少时会在WEB端增多缓存机制,以缩减对WCF的调用,而在WCF的互联网通讯中,数据类型1般
不会选择poco实体,因为它会有那一个对当下事务无用的字段,大家会为切实作业建立具体的DTO对象,而entity实体与DTO实体之间的赋值进度我们能够用AutoMapper来完毕。

2、数据传输对象DTO的引进

日前介绍了直白采纳Entity
Framework实体类对象的坏处,并且只借使手拉手到底都选用那一个实体类,里面的多数对象引用都以空的,对我们在界面层使用不便,而且也说不定引发了重重WCF框架里面包车型地铁部分相关主题材料。
咱俩办事处方的标题,引进了三个DTO(数据传输对象)的东西。
数码传输对象(DTO)是不曾作为的POCO对象,它的目标只是为了对世界对象开始展览数量封装,达成层与层之间的数码传递,分界面表现层与应用层之间是经过数量传输对象(DTO)进行互动的。数据传输对象DTO自己并不是职业对象,数据传输对象是依照UI的供给进行统筹的。
本条目的和现实性多少存款和储蓄的实体类是独自的,它能够说是实体类的三个映射体,名称能够和实体类分化,属性数据也足以实体类不一致样。那么既然在实体对象层外引进了此外一个DTO对象层,那么相互转变肯定是避免不了的了,大家为了制止手工业的炫人眼目情势,引进了其余三个有力的自动化映射的工具AutoMapper,来帮衬大家飞快、高效、智能的落成多少个层对象的映射处理。

公海赌船网址 1

AutoMapper的运用比较简单,1般只要指标属性一贯,他们会落实属性自动映射了,如下所示。

Mapper.CreateMap<RoleInfo, Role>();

假定两者的习性名称差异样,那么能够透过ForMember格局钦命,类似下边代码所示。

AutoMapper.Mapper.CreateMap<BlogEntry, BlogPostDto>() 
  .ForMember(dto => dto.PostId, opt => opt.MapFrom(entity => entity.ID));

AutoMapper也能够把映射音信写到一个类里面,然后统一举办加载。

Mapper.Initialize(cfg => { cfg.AddProfile<OrganizationProfile>();});

那么依据上边的图示格局,由于我们采纳代码生成工具自动生成的DTO和Entity,他们属性名称是保持一致的,那么大家只要求在应用层对它们两者对象开始展览互动映射就能够了。

public class RoleService : BaseLocalService<RoleInfo, Role>, IRoleService
{               
    private IRoleBLL bll = null;

    public RoleService() : base(IFactory.Instance<IRoleBLL>())
    {
        bll = baseBLL as IRoleBLL;

        //DTO和Entity模型的相互映射
        Mapper.CreateMap<RoleInfo, Role>();
        Mapper.CreateMap<Role, RoleInfo>();
    }
}

基于这几个里面对接的酷炫关系,大家就能够在Facade接口层提供统一的DTO对象服务,而职业逻辑层(也正是应用Entity
Framework
实体框架的处理成)则依然选拔它的Entity对象来传递。上面作者提供多少个包装好的基类接口供了然DTO和Entity的互动衔接处理。

一)传入DTO对象,并转移为Entity对象,使用EF对象插入。

/// <summary>
/// 插入指定对象到数据库中
/// </summary>
/// <param name="dto">指定的对象</param>
/// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>
public virtual bool Insert(DTO dto)
{
    Entity t = dto.MapTo<Entity>();
    return baseBLL.Insert(t);
}

二)根据条件从EF框架中获取Entity对象,并改变后再次来到DTO对象

/// <summary>
/// 查询数据库,返回指定ID的对象
/// </summary>
/// <param name="id">ID主键的值</param>
/// <returns>存在则返回指定的对象,否则返回Null</returns>
public virtual DTO FindByID(object id)
{
    Entity t = baseBLL.FindByID(id);
    return t.MapTo<DTO>();
}

三)根据标准从EF框架中得到Entity集合对象,并改造为DTO列表对象

/// <summary>
/// 返回数据库所有的对象集合
/// </summary>
/// <returns></returns>
public virtual ICollection<DTO> GetAll()
{
    ICollection<Entity> tList = baseBLL.GetAll();
    return tList.MapToList<Entity, DTO>();
}

二、数据传输对象DTO的引进

眼下介绍了第三手行使Entity
Framework实体类对象的弊病,并且只假设同台到底都采用这些实体类,里面的许多对象引用都以空的,对我们在分界面层使用不便,而且也说不定引发了广大WCF框架里面包车型客车1些生死相依难题。

小编们依照上边的标题,引进了三个DTO(数据传输对象)的事物。

数量传输对象(DTO)是未曾表现的POCO对象,它的目标只是为着对天地对象进行数据封装,完结层与层之间的多少传递,分界面表现层与应用层之间是通过数量传输对象(DTO)进行互动的。数据传输对象DTO本身并不是工作对象,数据传输对象是依据UI的急需开展统一筹划的。

其一指标和切实数量存款和储蓄的实体类是独立的,它能够说是实体类的四个映射体,名称可以和实体类分化,属性数据也得以实体类不一致。那么既然在实业对象层外引进了其余1个DTO对象层,那么相互转变料定是制止不了的了,大家为了防止手工业的映射方式,引进了别的三个强大的自动化映射的工具AutoMapper,来增派大家快捷、高效、智能的贯彻多少个层对象的炫丽处理。

公海赌船网址 2

AutoMapper的选取比较轻松,壹般只要目的属性一贯,他们会完成属性自动映射了,如下所示。

Mapper.CreateMap<RoleInfo, Role>();

假如两岸的天性名称分化,那么能够通过ForMember形式钦点,类似上边代码所示。

AutoMapper.Mapper.CreateMap<BlogEntry, BlogPostDto>()
                .ForMember(dto => dto.PostId, opt => opt.MapFrom(entity => entity.ID));

AutoMapper也足以把映射音讯写到四个类里面,然后统一进行加载。

Mapper.Initialize(cfg => {
  cfg.AddProfile<OrganizationProfile>();
});

那么依据下边包车型地铁图示形式,由于我们选替代码生成工具自动生成的DTO和Entity,他们属性名称是保持一致的,那么大家只要求在应用层对它们两者对象开始展览交互映射就能够了。

    public class RoleService : BaseLocalService<RoleInfo, Role>, IRoleService
    {               
        private IRoleBLL bll = null;

        public RoleService() : base(IFactory.Instance<IRoleBLL>())
        {
            bll = baseBLL as IRoleBLL;

            //DTO和Entity模型的相互映射
            Mapper.CreateMap<RoleInfo, Role>();
            Mapper.CreateMap<Role, RoleInfo>();
        }
    }

依照那几个里面对接的投射关系,大家就足以在Facade接口层提供统壹的DTO对象服务,而工作逻辑层(约等于采取Entity
Framework
实体框架的处理成)则依然利用它的Entity对象来传递。下边作者提供几个包装好的基类接口供掌握DTO和Entity的并行衔接处理。

一)传入DTO对象,并更改为Entity对象,使用EF对象插入。

        /// <summary>
        /// 插入指定对象到数据库中
        /// </summary>
        /// <param name="dto">指定的对象</param>
        /// <returns>执行成功返回<c>true</c>,否则为<c>false</c></returns>
        public virtual bool Insert(DTO dto)
        {
            Entity t = dto.MapTo<Entity>();
            return baseBLL.Insert(t);
        }

二)依据标准从EF框架中拿走Entity对象,并调换后归来DTO对象

        /// <summary>
        /// 查询数据库,返回指定ID的对象
        /// </summary>
        /// <param name="id">ID主键的值</param>
        /// <returns>存在则返回指定的对象,否则返回Null</returns>
        public virtual DTO FindByID(object id)
        {
            Entity t = baseBLL.FindByID(id);
            return t.MapTo<DTO>();
        }

3)遵照规则从EF框架中得到Entity集合对象,并转移为DTO列表对象

        /// <summary>
        /// 返回数据库所有的对象集合
        /// </summary>
        /// <returns></returns>
        public virtual ICollection<DTO> GetAll()
        {
            ICollection<Entity> tList = baseBLL.GetAll();
            return tList.MapToList<Entity, DTO>();
        }

 

AutoMapper在先后中的突显:

三、Entity Framework 实体架构

依照方便管理的指标,每个模块都得以应用一种固定分层的秘诀来组织模块的政工内容,每一个模块都以以麻雀虽小、5脏俱全的政策实行。实例模块的任何业务逻辑层的档次布局如下所示。

公海赌船网址 3

假定考虑动用WCF,那么全部的协会和作者事先的混杂框架大约,各种模块的义务基本没什么变化,可是由原来在DAL层分开的11实现层,变化为各种数据库的Mapping层了,而模型扩充了DTO,具体项目布局如下所示。

公海赌船网址 4

实际的品类表达如下所示:
EFRelationship

系统的事务模块及接口、数据库访问模块及接口、DTO对象、实体类对象、种种数据库映射Mapping类等皮之不存毛将焉附内容。该模块内容紧凑结合Database二Sharp庞大代码生成工具生成的代码、各层高度抽象承继及运用泛型扶助多数据库。

EFRelationship.WCFLibrary
系统的WCF服务的事情逻辑模块,该模块通过引用文件措施,把业务管理逻辑放在1块儿,方便WCF服务配置及调用。

EFRelationshipService
框架WCF服务模块,包蕴基础服务模块BaseWcf和事务服务模块,他们为了便利,分开管理发布。

EFRelationship.Caller
概念了切实业务模块完结的Façade应用接口层,并对Winform调用格局和WCF调用格局开始展览包装的档次。

现实我们以三个会员系统规划为例,它的程序集关系如下所示。

公海赌船网址 5

咱俩来看看整个框架结构的筹划作用如下所示。

公海赌船网址 6

内部工作逻辑层模块(以及任何应用层)我们提供了重重根据实体框架的公用类库(WHC.Framework.EF),在这之中的一而再关系大家将它推广,领会在那之中的接续细节关系,效果如下所示。

公海赌船网址 7

上海体育场地很好的概述了自个儿的EF实体框架的安插思路,那几个层最终依旧经过代码生成工具Database二Sharp进行全部的改变,以加强急速生产的目标,并且统1全部的命名规则。前边有时机再写壹篇小说介绍代码生成的逻辑部分。
上海教室左侧优秀的八个工厂类,八个IFactory是依据本地区直属机关连格局,也正是一贯动用EF框架的靶子开始展览拍卖;二个CallerFactory是基于Facade层完成的接口,依据配置指向WCF数据服务对象,只怕直连对象开始展览多少的操作处理。

三、Entity Framework 实体框架结构

依据方便管理的指标,每一种模块都足以应用1种长久分层的措施来公司模块的作行业内部容,每个模块都以以麻雀虽小、伍脏俱全的宗旨施行。实例模块的总体育赛事情逻辑层的品种结构如下所示。

公海赌船网址 8

假使设想采纳WCF,那么全体的构造和自家事先的搅和框架大概,各类模块的任务基本没什么变化,然则由原本在DAL层分开的逐1达成层,变化为种种数据库的Mapping层了,而模型增添了DTO,具体品种结构如下所示。

公海赌船网址 9

切切实实的连串表明如下所示:

EFRelationship

系统的业务模块及接口、数据库访问模块及接口、DTO对象、实体类对象、各种数据库映射Mapping类等相关内容。该模块内容紧密结合Database2Sharp强大代码生成工具生成的代码、各层高度抽象继承及使用泛型支持多数据库。

EFRelationship.WCFLibrary

系统的WCF服务的业务逻辑模块,该模块通过引用文件方式,把业务管理逻辑放在一起,方便WCF服务部署及调用。

EFRelationshipService

框架WCF服务模块,包括基础服务模块BaseWcf和业务服务模块,他们为了方便,分开管理发布。

EFRelationship.Caller

定义了具体业务模块实现的Façade应用接口层,并对Winform调用方式和WCF调用方式进行包装的项目。

切实大家以三个会员系统规划为例,它的先后集关系如下所示。

公海赌船网址 10

小编们来探视整个架构的筹划功效如下所示。

公海赌船网址 11

里面工作逻辑层模块(以及任何应用层)我们提供了诸多依据实体框架的公用类库(WHC.Framework.EF),个中的承接关系大家将它推广,精通当中的持续细节关系,效果如下所示。

公海赌船网址 12

上图很好的概述了自家的EF实体框架的安插思路,这一个层最后依旧经过代码生成工具Database2Sharp进行全部的更动,以加强快捷生产的目标,并且统壹全体的命名规则。前面有空子再写一篇随笔介绍代码生成的逻辑部分。

上海教室左侧出色的三个厂子类,多少个IFactory是依照本地直连情势,也便是一贯利用EF框架的目的开始展览处理;一个CallerFactory是基于Facade层实现的接口,依据铺排指向WCF数据服务对象,只怕直连对象开始展览数量的操作处理。

那个类别小说如下所示:

Entity Framework
实体框架的造成之旅–基于泛型的蕴藏格局的实体框架(一)

Entity Framework
实体框架的变异之旅–利用Unity对象重视注入优化实体框架(二)
 

Entity Framework
实体框架的朝令夕改之旅–基类接口的联结和异步操作的实现(三)

Entity Framework 实体框架的多变之旅–实体数据模型
(EDM)的处理(四)

Entity Framework 实体框架的产生之旅–Code
First的框架设计(伍)
 

Entity Framework 实体框架的朝令暮改之旅–Code First方式中利用 Fluent API
配置(陆)

Entity Framework
实体框架的多变之旅–数据传输模型DTO和实人体模型型Entity的分离与一块

 

DTO实体

[DataContract]
    public class ProductDTO
    {
        [DataMember]
        public int ProductID { get; set; }
        [DataMember]
        public string ProductName { get; set; }
        [DataMember]
        public System.DateTime CreateDate { get; set; }
        [DataMember]
        public int SaleCount { get; set; }
        [DataMember]
        public Nullable<int> ClickCount { get; set; }
        [DataMember]
        public string Info { get; set; }
        [DataMember]
        public int UserID { get; set; }
        [DataMember]
        public decimal SalePrice { get; set; }
        [DataMember]
        public int Discount { get; set; }
    }

POCO实体:

 public partial class Product
    {
        public Product()
        {
            this.ProductDetail = new HashSet<ProductDetail>();
        }
        public int ProductID { get; set; }
        public string ProductName { get; set; }
        public System.DateTime CreateDate { get; set; }
        public int SaleCount { get; set; }
        public Nullable<int> ClickCount { get; set; }
        public string Info { get; set; }
        public int UserID { get; set; }
        public decimal SalePrice { get; set; }
        public int Discount { get; set; }
        public System.DateTime UpdateDate { get; set; }

        public virtual User_Info User_Info { get; set; }
        public virtual ICollection<ProductDetail> ProductDetail { get; set; }
    }

上面采取AutoMapper实现指标四个实体的赋值,这是WCF服务中的代码片断:

public class ProductService : ServiceBase, IProductService
    {

        //通过ServiceLocator从IoC容器中获得对象
        IProductRepository productRepository = ServiceLocator.Instance.GetService<IProductRepository>();

        #region IProductService 成员

        public ProductDTO CreateProduct(ProductDTO productDTO)
        {
            Mapper.CreateMap<ProductDTO, Product>();
            Product product = Mapper.Map<ProductDTO, Product>(productDTO);
            productRepository.AddProduct(product);
            return productDTO;
        }

        public List<ProductDTO> GetProduct()
        {
            Mapper.CreateMap<Product, ProductDTO>();
            List<ProductDTO> arr = new List<ProductDTO>();
            productRepository.GetProduct().ForEach(i =>
            {
                arr.Add(Mapper.Map<Product, ProductDTO>(i));
            });
            return arr;
        }

        public ProductDTO ModifyProduct(ProductDTO productDTO)
        {
            Mapper.CreateMap<ProductDTO, Product>();
            Product product = Mapper.Map<ProductDTO, Product>(productDTO);
            productRepository.ModifyProduct(product);
            return productDTO;
        }

        #endregion
    }

如何,那种艺术的对象赋值很爽吧,呵呵。

 再次回到目录

相关文章