Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将实体映射到DTO而不使用重复代码_C#_Entity Framework_Entity Framework 6_Dto - Fatal编程技术网

C# 将实体映射到DTO而不使用重复代码

C# 将实体映射到DTO而不使用重复代码,c#,entity-framework,entity-framework-6,dto,C#,Entity Framework,Entity Framework 6,Dto,我正试图解决这个问题,在N层应用程序中使用实体框架(6)。由于来自存储库(包含与数据库的所有通信)的数据应该在更高的层(UI、服务等)中使用,因此我需要将其映射到DTO 在数据库中,存在相当多的多对多关系,因此数据结构可能/将在应用程序生命周期的某个阶段变得复杂。我偶然发现,在编写存储库方法时,我正在重复完全相同的代码。我的FirmRepository就是一个例子,它包含一个GetAll()方法和GetById(int-firmId)方法 在GetById(int-firmId)方法中,我有以下

我正试图解决这个问题,在N层应用程序中使用实体框架(6)。由于来自存储库(包含与数据库的所有通信)的数据应该在更高的层(UI、服务等)中使用,因此我需要将其映射到DTO

在数据库中,存在相当多的多对多关系,因此数据结构可能/将在应用程序生命周期的某个阶段变得复杂。我偶然发现,在编写存储库方法时,我正在重复完全相同的代码。我的
FirmRepository
就是一个例子,它包含一个
GetAll()
方法和
GetById(int-firmId)
方法

GetById(int-firmId)
方法中,我有以下代码(不完整,因为有很多关系需要映射到DTO):

public DTO.Firm GetById(int-id)
{
//返回结果
var结果=新的DTO.Firm();
尝试
{
//数据库连接
使用(var ctx=new MyEntities())
{
//从数据库中获取公司信息
var公司=(来自ctx公司中的f
其中f.ID==ID
选择f).FirstOrDefault();
//如果找到公司,则开始映射到DTO对象
如果(坚定!=null)
{
结果.地址=公司.地址;
result.Address2=firm.Address2;
结果.增值税=公司.增值税;
result.Email=firm.Email;
//地图Zipcode和城市
result.City=new DTO.City()
{
CityName=firm.City.City1,
ZipCode=firm.City.ZipCode
};
//地图ISO代码和国家/地区
result.Country=新的DTO.Country()
{
CountryName=firm.Country.Country1,
ISO=firm.Country.ISO
};
//检查该公司是否有任何专有参数
if(firm.ExclusiveParameterType\u Product\u firm.Any())
{
var exclusiveParamsList=新列表();
//映射独占参数类型
foreach(公司内var参数。独家参数类型产品公司)
{
//继续之前,请检查独占参数类型是否为null
if(param.ExclusiveParameterType!=null)
{
//创建新的独占参数类型DTO
var exclusiveParameter=新的DTO.ExclusiveParameterType()
{
ID=param.ExclusiveParameterType.ID,
Description=param.ExclusiveParameterType.Description,
Name=param.ExclusiveParameterType.Name
};
//将新的DTO添加到列表中
排他性参数列表。添加(排他性参数);
}
}
//要映射的对象多得多。。。。
//在结果对象上设置列表
result.ExclusiveParameterTypes=exclusiveParamsList;
}
}
}
//返回DTO
返回结果;
}
捕获(例外e)
{
//日志异常
Logging.Instance.Error(e);
//只需返回null
返回null;
}
}
这只是一种方法。然后,
GetAll()
方法将具有完全相同的映射逻辑,从而产生重复的代码。此外,当添加更多方法时,即
Find
Search
方法,需要再次复制相同的映射。当然,这并不理想

我已经读了很多关于著名的AutoMapper框架的书,该框架可以将实体映射到DTO或从DTO映射到实体,但是由于我有这些多对多关系,它很快就会因为AutoMapper配置代码而感到臃肿。我也读过这篇文章,在我看来很有意义:

有没有其他方法可以在不反复复制/粘贴相同代码的情况下执行此操作


提前谢谢

另一种策略是使用类构造函数和
显式
和/或
隐式
转换运算符的组合。它允许您将一个用户定义的实体强制转换为另一个实体。该特性还有一个额外的好处,就是将流程抽象出来,这样您就不会重复自己

在您的
DTO.Firm
类中,定义显式或隐式运算符(注意:我正在对您的类的名称进行假设):

然后,您可以在存储库代码中使用它,如下所示:

public DTO.Firm GetById(int id) {
  using (var ctx = new MyEntities()) {
    var firm = (from f in ctx.Firms
                where f.ID == id
                select f).FirstOrDefault();

    return (DTO.Firm)firm;
  }
}

public List<DTO.Firm> GetAll() {
  using (var ctx = new MyEntities()) {
    return ctx.Firms.Cast<DTO.Firm>().ToList();
  }
}
public DTO.Firm GetById(int-id){
使用(var ctx=new MyEntities()){
var公司=(来自ctx公司中的f
其中f.ID==ID
选择f).FirstOrDefault();
返回(DTO.公司)公司;
}
}
公共列表GetAll(){
使用(var ctx=new MyEntities()){
返回ctx.Firms.Cast().ToList();
}
}

这是MSDN中的扩展方法。

您可以对实体公司(DB.firm)进行如下扩展

public static class Extensions
    {
        public static DTO.Firm ToDto(this DB.Firm firm)
        {
           var result = new DTO.Firm();
           result.Address = firm.Address;
           result.Address2 = firm.Address2;
           //...

           return result;    
        }
    }

然后可以在代码中的任意位置转换DB.Firm对象,如
Firm.ToDto()

关于映射:实际上,如果您使用Automapper或在某些方法中完全手动准备映射(扩展名1或其他答案中提到的显式强制转换操作符),这并不重要—关键是将其放在一个地方以实现可重用性

只是
public DTO.Firm GetById(int id) {
  using (var ctx = new MyEntities()) {
    var firm = (from f in ctx.Firms
                where f.ID == id
                select f).FirstOrDefault();

    return (DTO.Firm)firm;
  }
}

public List<DTO.Firm> GetAll() {
  using (var ctx = new MyEntities()) {
    return ctx.Firms.Cast<DTO.Firm>().ToList();
  }
}
public static class Extensions
    {
        public static DTO.Firm ToDto(this DB.Firm firm)
        {
           var result = new DTO.Firm();
           result.Address = firm.Address;
           result.Address2 = firm.Address2;
           //...

           return result;    
        }
    }