我想通过单个 WCF 服务将简单实体和联接作为 OData 公开。 给定艺术家及其专辑列表的域,我知道我可以有一个这样的 DbContext:
public class PickContext: DbContext {
public DbSet<Album> Albums { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<List> Lists { get; set; }
由此我可以制作这样的 OData 服务:
public class PickDataService : DataService<PickContext> {
public static void InitializeService(DataServiceConfiguration config) {
config.SetEntitySetAccessRule("Lists", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("Artists", EntitySetRights.AllRead);
config.SetEntitySetAccessRule("Albums", EntitySetRights.AllRead);
我也知道我可以引入一个类来将列表、艺术家和专辑展平化为联接,如下所示:
public class PickContainer {
private PickContext pickContext=new PickContext();
public IQueryable<Foo> Foos { get; private set; }
public PickContainer() {
Foos=from a in pickContext.Albums
select new Foo {
ID=a.ID, Title=a.Title, Rating=a.Rating, Newness=a.Newness, Chance=a.Chance,
LastChosen=a.LastChosen, Acquired=a.Acquired, Media=a.Media, ArtistID=a.ArtistID,
ArtistName=a.Artist.Name, ListID=a.Artist.ListID };
}
}
然后,我可以创建第二个服务来托管此联接实体:
public class PickService : DataService<PickContainer> {
public static void InitializeService(DataServiceConfiguration config) {
config.SetEntitySetAccessRule("Foos", EntitySetRights.AllRead);
但我无法弄清楚的是,是否有办法将两组实体放在一个容器中,更重要的是,在一个服务中。 这可能吗? 我已经玩过 $expand=Artist,但是如果我在客户端上使用扁平模型,我的生活会更轻松。 当我尝试在 PickContext 中包含 Foos 并将其添加到 PickDataService 时,我收到异常"在实体集中找不到给定名称'Foos'"。
WCF 使用实体框架的特定数据服务提供程序。您可以在此处了解更多信息。每个服务仅使用一个提供程序。不能在一个服务中混合使用多个提供程序。
您尝试在同一服务中混合使用实体框架提供程序 (PickContext) 和反射提供程序 (PickContainer),但 WCF 数据服务不支持此功能,因为您只能为一个服务提供一个提供程序。
但是,您可以通过 Web API 将其存档。
请考虑设置以下控制器:
public class AlbumsController : ODataController
{
[Queryable]
public IQueryable<Album> Get()
{
return new PickContext().Albums;
}
}
public class FoosController : ODataController
{
[Queryable]
public IQueryable<Foo> Get()
{
var Foos = from a in new PickContext().Albums
select new Foo
{
ID = a.ID,
};
return Foos;
}
}
并在路由配置部分添加以下内容:
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<Album>("Albums");
builder.EntitySet<Foo>("Foos");
IEdmModel model = builder.GetEdmModel();
config.Routes.MapODataRoute(
routeName:"odata",
routePrefix:"odata",
model: model
);
然后,您可以在同一服务根目录下访问两者:
http://host/odata/Albums
http://host/odata/Foos