[英]OData over a “View” of unioned data in Entity Framework
我正在開發一個OData服務,該服務公開了使用Entity Framework 6創建的模型。這些實體是只讀的,並且加載非常大。 (幾千兆字節)
為了實現這一點,我正在使用Microsoft.OData.EntityFrameworkProvider,(我目前沒有使用WebAPI)這大部分工作正常,但是我有一個新的需求,需要公開一個實際上是多個其他實體的聯合的實體方便我們的EndUser /客戶。
EF Context Snippet
...
public DbSet<Foo> FooRecs { get; set; }
public DbSet<Bar> BarRecs { get; set; }
public IQueryable<FooBarRec> FooBarRecs
{
get
{
return FooRecs.Select(f => new FooBarRec() { Id = f.Id, Description = f.Description })
.Union(
BarRecs.Select(b => new FooBarRec() { Id = b.Id, Description = b.Description })
);
}
}
...
我無法通過odata公開這個IQueryable屬性,因為看起來EntityFrameworkProvider只暴露DbSets而不是任何IQueryable對象,這是有道理的。
我的問題是,使用OData實現這一目標的最佳方法是什么?
我想避免將重復數據加載到第三個中間表中,因為數據可能很大,加載數據的時間是每晚完成的。 似乎QueryInterceptor只允許您對已經查詢的數據進行子過濾,這樣看似不起作用。
我嘗試做一些瘋狂的事情,比如擴展DbSet和制作我自己的DbViewSet,它在它的構造函數中接受兩個集合,但是找不到關閉循環的方法。
使用OData和EF6完成類似於視圖的最佳方法是什么?
謝謝!
我用Web API和OData創建了一個示例。 它看起來很簡單,可以滿足您的要求:
首先,我定義以下CLR類來映射您的類型,而不需要創建任何視圖:
public class FooBarRec
{
public int Id { get; set; }
public string Name { get; set; }
public Foo FooRec { get; set; }
public Bar BarRec { get; set; }
}
public class Foo
{
public int FooId { get; set; }
public string FooName { get; set; }
}
public class Bar
{
public int BarId { get; set; }
public string BarName { get; set; }
}
接下來,我基於以上CLR類型創建OData EdmModel:
private static IEdmModel GetEdmModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<FooBarRec>("FooBarRecs");
builder.EntitySet<Foo>("Foos");
builder.EntitySet<Bar>("Bars");
return builder.GetEdmModel();
}
接下來,我創建OData控制器來處理OData URI查詢:
// Controller
public class FoosController : ODataController
{
public const int Num = 10;
public static IList<Foo> foos = Enumerable.Range(0, Num).Select(i =>
new Foo
{
FooId = 100 + i,
FooName = "Foo #" + (100 + i)
}).ToList();
[EnableQuery]
public IHttpActionResult Get()
{
return Ok(foos);
}
}
public class BarsController : ODataController
{
public const int Num = 10;
public static IList<Bar> bars = Enumerable.Range(0, Num).Select(i =>
new Bar
{
BarId = 1000 + i,
BarName = "Bar #" + (1000 + i)
}).ToList();
[EnableQuery]
public IHttpActionResult Get()
{
return Ok(bars);
}
}
public class FooBarRecsController : ODataController
{
public const int Num = 10;
public static IList<FooBarRec> fooBarRecs = Enumerable.Range(0, Num).Select(i =>
new FooBarRec
{
Id = i,
Name = "ForBarRec #" + i
}).ToList();
static FooBarRecsController()
{
for(int i = 0; i < Num; i++)
{
fooBarRecs[i].FooRec = FoosController.foos[i];
fooBarRecs[i].BarRec = BarsController.bars[i];
}
}
[EnableQuery]
public IHttpActionResult Get()
{
return Ok(fooBarRecs);
}
}
現在,我們可以提供EndUser想要的任何數據。
例如,EndUser可以使用以下兩個URI來查詢單個數據:
〜/的OData /酒吧
或者,他可以使用以下URI來查詢Union數據:
就這樣。
正如Jodrell在評論中所說。
使這項工作的唯一方法是使DbSet表示SQL視圖。
我可以讓Entity Framework正確處理模型綁定的唯一方法是在創建表后刪除表,然后創建然后創建視圖。
因為它是一個聯合視圖,所以我必須在模型完成初始化之后處理它,否則它會嘗試在視圖上強制聚簇索引,如果視圖包含聯合,則不可能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.