Reputation: 1499
I have the following two classes:
public class Base
{
public int Id { get; set; }
public string PropertyA { get; set; }
}
[NotMapped]
public class Derived : Base
{
public string PropertyB { get; set; }
}
And I have the following Query:
var baseQ = from b in db.Bases
let propertyB = SomeCalculation()
select new { Base = b, PropertyB = propertyB };
This works as is. What i want is something like this (Pseudo-Code):
List<Derived> list = (from b in db.Bases
let propertyB = SomeCalculation()
select new { Base = b, PropertyB = propertyB }).ToList();
Is it possible to "Down-Cast" the selection to a derived class, or do I have to write a Constructor for the Derived class which looks something like this:
public Derived(Base b, string b) { ... }
My final solution: I changed the Derived Class to the following (since you even can't use a string.Format in the object initializer):
public class Derived
{
public Base Base { get; set; }
public string PropertyB { get; set; }
public string CalculatedProperty { get { ... } }//For string.Format and other stuff
}
And I'm doing the assignement as follows:
List<Derived> list = (from b in db.Bases
let propertyB = SomeCalculation()
select new Derived { Base = b, PropertyB = propertyB }).ToList();
Upvotes: 2
Views: 2305
Reputation: 28698
The accepted answer won't work because EF won't let you construct concrete types in the database. The workaround - it does allow you to select anonymous types.
Building on Ahmad's answer:
var aList = (from b in db.Bases
let propertyB = SomeCalculation()
select new
{
Id = b.Id,
PropertyA = b.PropertyA,
PropertyB = propertyB
}).ToList();
List<Derived> list = (from a in aList
select new Derived
{
Id = a.Id,
PropertyA = a.PropertyA,
PropertyB = a.PropertyB
}).ToList();
Calling ToList
on your query forces the query to be executed and the data to be retrieved into your application (i.e. it will no longer be executed in the database). aList
is now a list in memory, so you can select the items into new Derived
objects.
In simplest terms, the problem is that everything up until you call ToList
is compiled into a SQL query (to improve efficiency). This is normally a good thing, but the issue is that your database has no concept of Derived
and the query select new Derived
can't be converted into SQL.
Upvotes: 0
Reputation: 4907
List<Derived> list = db.Bases.ToList()
.Select(p => new Derived()
{
Id = b.Id,
PropertyA = b.PropertyA,
PropertyB = SomeCalculation(),
}).ToList();;
Upvotes: 1
Reputation: 96477
You can't cast in this case since what your query returns is an anonymous type. Instead, you could use an object initializer to set the properties to the Derived
class:
List<Derived> list = (from b in db.Bases
let propertyB = SomeCalculation()
select new Derived
{
Id = b.Id,
PropertyA = b.PropertyA,
PropertyB = propertyB
}).ToList();
If you have a ton of properties you could take the approach you suggested, or add a Data Transfer Object (DTO) that contains your properties, then use a library like AutoMapper to perform the mapping for you.
Upvotes: 3