如何将SQL查询结果用作实体框架中的对象?

时间:2016-09-17 09:21:08

标签: entity-framework

我使用EF(代码优先)在c#中创建数据分析过程。数据模型涉及大约十几个相互关联的类。其中大多数直接与现有数据库中的表相对应,但是一些关键的只读对象类型实际上是复杂的多步SQL查询的产物。我无法为查询创建视图或存储过程。

我希望能够使用像DbSet.SqlQuery()这样的东西将这些查询结果加载到EF对象中,并且仍然利用EF的ORM功能将它们与对象图的其余部分相关联。

我认为我想要的是在DbSet尝试从数据库填充基于查询的对象时覆盖EF的SQL SELECT代码的方法。这可能吗?有更好的替代方法吗?

2 个答案:

答案 0 :(得分:0)

我找到了一种适合我的方式,但它很笨拙。 (有更好的方法吗?)

假设Foo是一个poco类,它与一个昂贵的查询结果相对应,我希望在SQL中显式写入并用作只读EF对象图中的对象。 Foo包括外键和导航属性。我的dbContext有一个名为Foos的DbSet。

// Pre-req: prevent EF from trying to sync model with db, since Foos doesn't map to a db table.
public FooDbContext()
{
    Database.SetInitializer<FooDbContext>(null); 
}

// load the query data with SqlQuery() and Attach()
var foos = db.Foos.SqlQuery("<hand written SQL SELECT>", parameters);
foreach(var foo in foos) db.Foos.Attach(foo);

// Subsequently reference the data with .Local to prevent db hits (which would fail, since no Foo table in db.)
var result = db.Foos.Local.Select(...);

我必须显式加载相关对象,但所有关系关联都会自动发生。例如,假设Bar与Foo具有1对多,Foo具有BarId属性(以及Bar导航属性),并且Bar类可能具有可观察的Foos集合。如果Bars存储为db查找表,我可以执行db.Bars.Load(),或更多过滤的内容,如:

var barIds = db.Foos.Local.Select(f => f.BarId).Distinct().ToArray();
db.Bars.Where(b => barIds.Contains(b.barId)).Load();

然后我可以使用Foo.Bar或Bar.Foos,一切正常。

答案 1 :(得分:0)

您是否可以将任意查询写入存储过程?然后,您可以使用Entity框架将其映射到函数。