1

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?

MrKekson
  • 720
  • 6
  • 18
  • 1
    Where does the `BusinessName` come from? Is it from an entity related in any way to `Task`, is it accessible from a navigation property? – CodeCaster Dec 03 '15 at 15:39
  • No, it's not accessible as nav property, it come from a legacy table, but i can join() it up. If needed i can rewrite the base classes so it become a nav property, but that would take a while, so if it's possible i want an 'easier' answer something like select( t => new TaskView { task = task.base(), BusinessName = tablename.prop }). I'm not shure if it's possible, i know i can select 2 object into a third one, but not shure with inherited childs. – MrKekson Dec 03 '15 at 15:52

4 Answers4

2
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();
Robert McKee
  • 21,305
  • 1
  • 43
  • 57
  • And of course, you could always use one of the answer from here: http://stackoverflow.com/questions/930433/apply-properties-values-from-one-object-to-another-of-the-same-type-automaticall to copy all the properties if you think the properties of Task may change in the future. – Robert McKee Dec 03 '15 at 17:05
  • Working like a champ with the linq CopyProperties extension. Thanks mate! – MrKekson Dec 04 '15 at 13:44
1

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; }
    // ...
}
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • Yes, this is a good idea, so i just select the base task object, and the additional property. Trough serializing it to json wont be that nice, because of the additional wrapper object, but i can see it doing the job! If theere will be no answer for my question, i'll accept your workaround as an answer later. – MrKekson Dec 03 '15 at 15:45
1

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()
});
Maxim Goncharuk
  • 1,285
  • 12
  • 20
0

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"
};
Nick Prozee
  • 2,823
  • 4
  • 22
  • 49
  • Yes, i need something very similar, except if i hardcoded all the props like prop1 = o1.prop1, then i need to rewrite everything related if i change the Task() base class. So i want exactly this output, but is it possible to select like { this.base() = task, BusinessName = sometable.someprop } – MrKekson Dec 03 '15 at 16:31