我还在学习Entity Framework和Linq-To-Entities,我想知道这种声明是否可行:
using (var context = new MyEntities())
{
return (
from a in context.ModelSetA.Include("ModelB")
join c in context.ModelSetC on a.Id equals c.Id
join d in context.ModelSetD on a.Id equals d.Id
select new MyModelA()
{
Id = a.Id,
Name = a.Name,
ModelB = new MyModelB() { Id = a.ModelB.Id, Name = a.ModelB..Name },
ModelC = new MyModelC() { Id = c.Id, Name = c.Name },
ModelD = new MyModelD() { Id = d.Id, Name = d.Name }
}).FirstOrDefault();
}
我必须使用预先存在的数据库结构,这种结构不是很优化,因此我无法在没有大量额外工作的情况下生成EF模型。我认为简单地创建我自己的模型并将数据映射到它们会很容易,但我不断收到以下错误:
无法创建“MyNamespace.MyModelB”类型的常量值。只要 支持原始类型(例如Int32,String和Guid') 这个背景。
如果删除ModelB,ModelC和ModelD的映射,它将正确运行。我无法使用Linq-To-Entities创建新的嵌套类?或者我只是以错误的方式写这个?
答案 0 :(得分:4)
您拥有的内容可以与POCO(例如,视图模型)一起使用。 Here's an example.你无法以这种方式构建实体。
此外,join
为generally inappropriate for a L2E query.请改用实体导航属性。
答案 1 :(得分:2)
我在控制台应用程序中使用EF 4.1创建了您的模型(我如何理解它):
如果要对其进行测试,请添加对EntityFramework.dll
的引用,并将以下内容粘贴到Program.cs
中(如果安装了SQL Server Express,则自动创建数据库):
using System.Linq;
using System.Data.Entity;
namespace EFNestedProjection
{
// Entities
public class ModelA
{
public int Id { get; set; }
public string Name { get; set; }
public ModelB ModelB { get; set; }
}
public class ModelB
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ModelC
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ModelD
{
public int Id { get; set; }
public string Name { get; set; }
}
// Context
public class MyContext : DbContext
{
public DbSet<ModelA> ModelSetA { get; set; }
public DbSet<ModelB> ModelSetB { get; set; }
public DbSet<ModelC> ModelSetC { get; set; }
public DbSet<ModelD> ModelSetD { get; set; }
}
// ViewModels for projections, not entities
public class MyModelA
{
public int Id { get; set; }
public string Name { get; set; }
public MyModelB ModelB { get; set; }
public MyModelC ModelC { get; set; }
public MyModelD ModelD { get; set; }
}
public class MyModelB
{
public int Id { get; set; }
public string Name { get; set; }
}
public class MyModelC
{
public int Id { get; set; }
public string Name { get; set; }
}
public class MyModelD
{
public int Id { get; set; }
public string Name { get; set; }
}
class Program
{
static void Main(string[] args)
{
// Create some entities in DB
using (var ctx = new MyContext())
{
var modelA = new ModelA { Name = "ModelA" };
var modelB = new ModelB { Name = "ModelB" };
var modelC = new ModelC { Name = "ModelC" };
var modelD = new ModelD { Name = "ModelD" };
modelA.ModelB = modelB;
ctx.ModelSetA.Add(modelA);
ctx.ModelSetB.Add(modelB);
ctx.ModelSetC.Add(modelC);
ctx.ModelSetD.Add(modelD);
ctx.SaveChanges();
}
// Run query
using (var ctx = new MyContext())
{
var result = (
from a in ctx.ModelSetA.Include("ModelB")
join c in ctx.ModelSetC on a.Id equals c.Id
join d in ctx.ModelSetD on a.Id equals d.Id
select new MyModelA()
{
Id = a.Id,
Name = a.Name,
ModelB = new MyModelB() {
Id = a.ModelB.Id, Name = a.ModelB.Name },
ModelC = new MyModelC() {
Id = c.Id, Name = c.Name },
ModelD = new MyModelD() {
Id = d.Id, Name = d.Name }
}).FirstOrDefault();
// No exception here
}
}
}
}
这没有问题。 (我还在EF 4.0中重新创建了数据库中的模型(EF 4.1创建了这个模型):它也很有用。因为EF 4.1不会改变LINQ to Entities中的任何内容,所以不足为奇。)
现在问题是为什么你得到一个例外?我的猜测是,与上面的简单模型相比,您的模型或ViewModel或查询存在一些重要差异,这些模型在问题的代码示例中不可见。
但一般结果是:对嵌套(非实体)类的预测有效。 (我在许多情况下都使用它,即使是嵌套的集合。)回答你的问题标题是:是的。
答案 2 :(得分:0)
Craig发布的内容似乎不适用于嵌套实体。克雷格,如果我误解了你发布的内容,请纠正我。
以下是我提出的可行的解决方法:
using (var context = new MyEntities())
{
var x = (
from a in context.ModelSetA.Include("ModelB")
join c in context.ModelSetC on a.Id equals c.Id
join d in context.ModelSetD on a.Id equals d.Id
select new { a, b, c }).FirstOrDefault();
if (x == null)
return null;
return new MyModelA()
{
Id = x.a.Id,
Name = x.a.Name,
ModelB = new MyModelB() { Id = x.a.ModelB.Id, Name = x.a.ModelB..Name },
ModelC = new MyModelC() { Id = x.c.Id, Name = x.c.Name },
ModelD = new MyModelD() { Id = x.d.Id, Name = x.d.Name }
};
}
由于Entity Framework无法处理从查询中创建嵌套类的问题,我只是从查询中返回一个包含我想要的数据的匿名对象,然后将其映射到模型