简体   繁体   English

c#实体框架选择到派生子级

[英]c# Entity Framework select into derived child

So I need to select a Task() object, with it's Attachments() objects, with Include() , like this: 所以我需要选择一个Task()对象,它是Attachments()对象,并Include() ,如下所示:

var tmp = cntx.Tasks.Include( at => at.Attachments ).FirstOrDefault(t => t.Id == id ); 

It's working fine, MVC api controller can serialize it to a json, with all of it's Attachmnets listed, basically it's working wonderfully. 它工作正常,MVC api控制器可以将其序列化为json,列出了所有的Attachmnets,基本上它的运行非常好。

Now my problem is, that i need 3 additional string property (for clearer example, I only use +1 string below) in the Task() 现在我的问题是,我在Task()需要3个附加的字符串属性(为清楚起见,我仅在下面使用+1字符串Task()

 public class TaskView : DataClasses.Task {
    public string BusinessName { get; set; }
}

And those props are not navigational properties for Task() , in fact it's from a few other tables. 这些道具不是Task()导航属性,实际上是来自其他一些表。 Now I can join up the previous query, with the tables, but I'm not sure how to select the previous fully populated Task object, with all of it's navigational Attachment() objects, and cast it to TaskView obj, with the added BusinessName string. 现在,我可以将上一个查询与表连接起来,但是我不确定如何选择前一个完全填充的Task对象及其所有导航Attachment()对象,然后将其转换为TaskView obj,并添加BusinessName串。

Any thoughts? 有什么想法吗?

public class TaskView : DataClasses.Task {
    public string BusinessName { get; set; }
    // Create constructor for Task
    public TaskView(DataClasses.Task task)
    {
       // Copy properties here
    }
}

Then you can do this: 然后,您可以执行以下操作:

var tmp = cntx.Tasks
  .Include(at => at.Attachments)
  .Where(t => t.Id == id)
  .Select(t=> new TaskView(t) { BusinessName=...})
  .FirstOrDefault();

Or you can create a property on TaskView that sets (and possibly get) a Task from TaskView, and just set it in the LINQ query. 或者,您可以在TaskView上创建一个属性,该属性可以从TaskView设置(并可能)获得Task,然后只需在LINQ查询中进行设置即可。

Or do this: 或这样做:

public class TaskView {
    public string BusinessName { get; set; }
    public DataClasses.Task Task { get; set;}
}

Then: 然后:

var tmp = cntx.Tasks
  .Include(at => at.Attachments)
  .Where(t => t.Id == id)
  .Select(t=> new TaskView { Task=t,BusinessName=...})
  .FirstOrDefault();

A base class instance cannot be "cast" to a derived class instance. 基类实例不能“投射”到派生类实例。 You need to create a new TaskView instance and copy all the properties of the source Task . 您需要创建一个新的TaskView实例,并复制源Task所有属性。

If you can afford, it would be much better to switch to containment rather than inheritance like this 如果您负担得起,最好改用收容而不是像这样的继承

public class TaskView
{
    public Task Task { get; set; }
    public string BusinessName { get; set; }
    // ...
}

Don't confuse entities with transport layer and their view. 不要将实体与传输层及其视图混淆。 Better solution if you create two more classes for transport layer like this: 如果再为传输层创建两个以上的类,则是更好的解决方案:

public class TaskDto 
{
  public long Id {get; set;}
  public List<AttachmentsDto> Attachments {get; set;}
}
public class AttachmentsDto 
{
  public long Id {get; set;}
}

And two more for view without inheritance like previous. 还有两个像以前一样没有继承的视图。 Also you need to create some helper classes for mapping entity to dto and from dto to view. 此外,您还需要创建一些帮助程序类,以将实体映射到dto以及从dto映射到视图。

var dtos = cntx.Tasks.Include( at => at.Attachments ).FirstOrDefault(t => t.Id == id ).Select(x => new TaskDto 
{
  Id = x.Id,
  Attachments = x.Attachments.Select(y => new AttachmentsDto { Id = y.Id }).ToList()
});

Try it with select query, if I understand your question correctly. 如果我正确理解您的问题,请尝试使用选择查询。
Something like: 就像是:

var tmp = from o in cntx.Tasks.Include( at => at.Attachments ) 
were (o.id == id) 
select new TaskView()
{
 //Properties here
 //e.g
 Id = o.Id,
 Attachments = o.Attachments,
 BusinessName = "YourBusinessName"
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM