"In constructors and initializers, only property or field parameter bindings are supported" when using object initializer syntax
I'm getting a very odd problem in Entity Framework query that I literally spent hours on.
When a query is executed, I get an exception:
In constructors and initializers, only property or field parameter bindings are supported in LINQ to Entities.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.NotSupportedException: In constructors and initializers, only property or field parameter bindings are supported in LINQ to Entities.
I know this problem typically occurs when you invoke a constructor with parameters inside of the query. This is natural because LINQ to Entities can't know what's going on there.
However, my query only uses object initializer syntax to fill the values, and I assume the default parameterless constructor will be invoked:
private static readonly Func<MyEntities, int, MessageParty> _getUserMessagePartyQuery = CompiledQuery开发者_运维知识库.Compile(
( MyEntities ctx, int id ) =>
ctx.Users
.Where( u => u.ID == id )
.Select( u => new {
u, up = u.UserProfile, img = u.UserProfile.Image
})
.Select( info => new MessageParty
{
PartyID = id,
Title = info.u.FullName,
// Assignment below causes the failure:
Image = {
Image = info.img,
ExternalUrl = info.up.ExternalProfileImageUrl
},
} ).First()
);
To re-iterate, the part causing the failure is:
Image = {
Image = info.img,
ExternalUrl = info.up.ExternalProfileImageUrl
}
Image
is a property of type ImageInfo
, which is uber-simple class:
public class ImageInfo
{
public Model.Image Image
{
get;
set;
}
public string ExternalUrl
{
get;
set;
}
}
I'm clearly not doing anything else but simple property assignments. Why does this query fail?
Your current code is effectively:
MessageParty tmp = new MessageParty();
// Other stuff
tmp.Image.Image = info.img;
tmp.Image.ExternalUrl = info.up.ExternalProfileImageUrl;
In other words, it's setting properties of the existing ImageInfo
(if there is one) rather than creating a new ImageInfo
. This is called a nested object initializer.
I suspect you want it to be equivalent to:
MessageParty tmp = new MessageParty();
// Other stuff
ImageInfo tmpImage = new ImageInfo();
tmpImage.Image = info.img;
tmpImage.ExternalUrl = info.up.ExternalProfileImageUrl;
tmp.Image = tmpImage;
So change your query to use:
Image = new ImageInfo {
Image = info.img,
ExternalUrl = info.up.ExternalProfileImageUrl
}
Update: somebody posted a nice answer explaining where, any why I was wrong. Check it out.
After trying to reproduce the error on a different computer step by step, I finally found the problem source.
I correctly identified Image
assignment to be the problem source, however I was tremendously dumbfounded when I realized that specifying the class name explicitly solved the problem:
Image = new ImageInfo { // was: Image = {
Image = info.img,
ExternalUrl = info.up.ExternalProfileImageUrl
}
I thought new ImageInfo
would be optional with object initializer syntax that assumes default constructor of the matching type, but somehow it is mandatory, at least for LINQ to Entities.
精彩评论