我在商业模式中添加了一个列表字段。它尚未存储在数据库中,我希望暂时将其映射为以下内容:
return MyContext.Foos.Select(foo=> new Foo
{
Id = foo.Id,
Name = foo.Name,
RequiredFeatures = new List<string>()
}).ToList();
但是,实体框架抱怨它无法在LINQ to Entities查询中实例化新列表:
实现IEnumerable的类型'System.Collections.Generic.List`1 [[System.String,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]'无法在LINQ to Entities中初始化查询。
基本上,List<string>
是一个复杂类型,虽然它包含一个默认构造函数,但构造函数需要在使用列表之前运行一些初始化代码。实体框架只是不了解如何从SQL方面生成一个空列表。
我也尝试用空数组实现相同的结果:
return MyContext.Foos
.Select(foo=> new Foo
{
Id = foo.Id,
Name = foo.Name,
RequiredFeatures = new string[0]
}).ToList();
LINQ to Entities不支持LINQ表达式节点类型'NewArrayBounds。
同样,实体框架不支持该表达式,即使它更简单。所以我尝试了所有的最简单的表达式,用于新的数组:
return MyContext.Foos
.Select(foo=> new Foo
{
Id = foo.Id,
Name = foo.Name,
RequiredFeatures = { }
}).ToList();
在构造函数和初始值设定项中,LINQ to Entities中仅支持属性或字段参数绑定。
我知道另一种方法是首先将所有对象加载到内存中,然后通过C#初始化列表:
return MyContext.Foos.ToList()
.Select(foo=> new Foo
{
Id = foo.Id,
Name = foo.Name,
RequiredFeatures = new List<string>()
}).ToList();
然而,这似乎是一种解决方法,而不是一个实际的解决方案。如果我不想重新迭代集合,我该如何初始化列表?
答案 0 :(得分:4)
令人惊讶的是,虽然new string[0]
和{ }
不起作用,但new string[] { }
和new string[0] { }
却有效!
return MyContext.Foos.ToList()
.Select(foo=> new Foo
{
Id = foo.Id,
Name = foo.Name,
RequiredFeatures = new string[] { }
}).ToList();
但是,这确实有一个警告,即您无法将项目添加到列表中,因为它由数组支持,而不是实际列表。它们看起来在功能上都是相同的,我不确定为什么实体框架支持一些而不支持其他一些。
<强>支持的:强>
new string[] { }
new string[0] { }
不支持:
{ }
new string[0]
new List<string>()
new List<string> { }
new List<string>() { }
<强>支持的:强>
new [] { "foo" }
new string[] { "foo" }
new string[1] { "foo" }
new List<string> { "foo" }
new List<string>() { "foo" }
不支持:
{ "foo" }
有趣的是,Entity Framework支持带有值的列表,但不支持空列表。