微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何通过将实体转换为DTO来实现Linq查询?

如何解决如何通过将实体转换为DTO来实现Linq查询?

有3个实体,以这种方式表示:

**1 - entity**
class A
int id ;
int Name;

[Foreign key]
int id_B;

List C;


**2 - entity**
class B
int id ;
int Name;

List A;

**3 - entity**
class C
int id;
int Name;

[Foreign Key]
int id_A;

创建了一个实体DTO(只有外键,一切都一样)

1 
class ADTO
int id ;
int Name;
List C;


2 
class BDTO
int id ;
int Name;
List A;

3 
class CDTO
int id;
int Name;

现在请求看起来像这样:

var quer = (await _context.A
                                    .Include(b => b.B)
                                        .Include(c => c.C)
                                              .Where(u => u.Id == 1).ToListAsync())
                                                .Select(a => new ADto
                                                {
                                                    Id = a.Id,//How to get information about entity B here by converting to DTO                                                   
                                                    C = a.C.Select(cdto => new CDTO{ Id = cdto.Id,Name = cdto.Name}).ToList(),});

如何通过转换为DTO在此处获取有关实体B的信息?

解决方法

通常,我建议您实现一个接口,该接口在结果对象的构造函数中提供

如此:

public interface IDbOjbect{
   int Id {get;set;}
   string Name{get;set;}
}

然后在您的DTO对象上

public Class DtoObject {
    public DtoOjbect(IDbOjbect source)
    {
        //Mapping done here.
    }

}

因为这样您就可以在任何持久层对象上实现该接口,并且映射仍将起作用。

因为linq查询很简单:

DbOjbectList.Select(x => new DtoObject(x));

提供的DtoOjbect实现了该接口。

您的C看起来像这样:

public partial class C {
   public int id {get;set;}
   public string Name {get;set;}  
}

public partial class C : IDbOjbect {
   
}

,您的CDTO如下:

public Class CDTO{

 public int Id {get;set;}
 public string Name {get;set;}

        public CDTO(IDbOjbect source)
        {
            Id = source.Id;
            Name = source.name;
        }
    }

想从B制作DTO吗?

在您的B上实施IDbOjbect

使用

public partial class B {
       public int id {get;set;}
       public string Name {get;set;}  
    }

    public partial class B : IDbOjbect {
       
    }

现在任何C或B都可以制成CDTO。

最好的部分是,您可以为B和C创建一个通用方法,在通用定义后使用“ Where”关键字,然后使用Interface作为类型,现在您可以创建一个执行相同操作的方法基于接口实现的东西,如果在A上实现接口,这对A也适用。

无需进一步修改。

现在您问的是问题,原来的问题就没有了,让我们扩展一下。

假设您有一个ResumeInfo对象,只有B可用。

然后将NullPointer模式与接口隔离原理一起使用。

因此您可以在resumeInfo类上创建一个接口

示例:

public interface IResumeInfo
{
    string PlaceOfEmployment {get;set;}
    DateTime StartOfEmployment {get;set;}
    DateTime? EndOfEmployment {get;set;}

}

然后在您的ResumeInfo对象上:

public partial class ResumeInfo
{
        string PlaceOfEmployment {get;set;}
        DateTime StartOfEmployment {get;set;}
        DateTime? EndOfEmployment {get;set;}
}

public partial class ResumeInfo : IResumeInfo
{

}

然后可以说您想要一个DTO对象:

public class DTOUserAndResume
{

       public int id {get;set;}
       public string Name {get;set;} 

       string PlaceOfEmployment {get;set;}
       DateTime StartOfEmployment {get;set;}
       DateTime? EndOfEmployment {get;set;}

   public DTOUserAndResume(IDbOjbect source,IResumeInfo resumeInfo)
   {
      Id = source.Id;
      Name = source.name;

      PlaceOfEmployment = resumeInfo.PlaceOfEmployment;
      StartOfEmployment = resumeInfo.StartOfEmployment ;
      EndOfEmployment = resumeInfo.EndOfEmployment ;

   }
}

现在在B上?我想您说您有简历数据,但没有C信息?

您在两者上都实现了IResumeInfo,但是在B上,您仅获得了任何数据,但是在C上却没有数据? NullOjbect模式。

实施接口,但使其不返回任何内容。

因此PlaceOfEmployment始终为“”或Null。 起始数据始终为1900-01-01 00:00:00或任何您希望“无”的对象都不能为空的对象,而在工作结束时为null。

因此,您只是声称数据是不存在的数据集的等同物,因为它没有要提供的数据集。

但是您不需要制作新的DTO,只需在CDTO上更新构造函数,它也可以正常工作。在命名和内容方面可能会有些混乱。

这应该导致呼叫如下:

C = a.C.Select(cdto => new CDTO{cdto,cdto.ResumeInfo}).ToList();
,

如果您要查询“ A”作为顶级实体,那么我认为您只是缺少与其关联的“ B”的导航属性。 (因为它包含B_Id FK)

1-实体

public class A
{
    public int id { get; set; }
    public string Name { get; set; }

    [ForeignKey("B")]
    public int id_B { get; set; } 

    public virtual B B { get; set; }

    public virtual ICollection<C> Cs { get; set;} = new List<C>();
}

然后,当您使用Select将实体投影到DTO时:

var query = (await _context.A
   .Where(a => a.Id == 1)
   .Select(a => new ADto
   {
       Id = a.Id,B = new BDTO { Id = a.B.Id /* ... */ },Cs = a.Cs.Select(c => new CDTO{ Id = c.Id,Name = c.Name}).ToList(),}).Single();

请注意,在使用.Select时,您无需使用.Include来引用相关实体,这仅用于急于加载要返回实体图的相关实体。 (例如,从DTO读取实体以更新 值时)。另外,在使用ToList之前请小心使用任何Select操作,因为这会将实体加载到内存中应用过滤器之类的内容,并否定查询的优化以仅满足Select的需求。 });

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。