简体   繁体   中英

c# Entity Framework select into derived child

So I need to select a Task() object, with it's Attachments() objects, with Include() , like this:

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.

Now my problem is, that i need 3 additional string property (for clearer example, I only use +1 string below) in the 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. 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.

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.

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 .

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.

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"
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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