A rather complicated object mapping I've inherited uses static Expression<Func<...>> in the .Select call (from my research these seem to be called "Expression Trees", but for brevity I'll refer to them as "Projections"). E.G. ProjectionItem.MainProjection is used to map results of a query on the FooBarObject table to instances of the ProjectionItem class:
// the query
_repo.Query<FooBarObject>()
.Select(ProjectionItem.MainProjection);
// elsewhere...
public class ProjectionItem
{
public int Foo { get; set; }
public int Bar { get; set; }
public int YaddaYadda { get; set; }
public static Expression<Func<FooBarObject, ProjectionItem>> MainProjection
{
get
{
return x => new ProjectionItem
{
Foo = x.Foo,
Bar = x.SomeOtherStuff.AndMoreStuff
.ThisDoesSomething(),
YaddaYadda = x.YouGetTheDrill,
// in reality there's like 80 more columns being mapped
};
}
}
}
However, now we want another "Projection" for the same FooBarObject table that'd be NEARLY identical to MainProjection except for 3-4 columns. Is there a way to define the shared properties between these "Projections" in one place to cut down on code duplication? I am aware the most correct solution is probably to just... rewrite this whole thing as a normal query, but let's work under the assumption that in this scenario, I just can't right now.
I tried adding a constructor to the ProjectionItem class that would house all shared logic between the "Projections":
public class ProjectionItem
{
public int Foo { get; set; }
public int Bar { get; set; }
public int YaddaYadda { get; set; }
public ProjectionItem(FooBarObject x)
{
Foo = x.Foo;
Bar = x.SomeOtherStuff.AndMoreStuff
.ThisDoesSomething();
}
public static Expression<Func<FooBarObject, ProjectionItem>> MainProjection
{
get
{
return x => new ProjectionItem(x)
{
YaddaYadda = x.YouGetTheDrill,
};
}
}
public static Expression<Func<FooBarObject, ProjectionItem>> NewProjection
{
get
{
return x => new ProjectionItem(x)
{
YaddaYadda = x.YouGetTheDrill + 1,
};
}
}
}
But that attempt resulted in this exception:
System.NotSupportedException: 'Only parameterless constructors and initializers are supported in LINQ to Entities.'
NOTE: this project is still on .NET Framework 4.6 and is using Entity Framework for its database interactions
.ThisDoesSomething()isn't something that maps to SQL, those projections can only run on the client, once the objects are loaded. There's no "inheritance" here, especially since those are static methods. You're asking if one static method can "inherit" from another static method - that's not possible.Foo=x.FooorCustomerName=x.Customer.Name). You can also create more complex mappings. With the Queryable extensions those mappings can be applied to any IQueryable<> and in the case of EF, alter the generatedSelectclauses. You still need to ensure the mappings can be translated to SQL.