这实际上是一个EF Code First问题,但有时OData的上下文会有所不同。问题很简单。我们的基础SQL Server表/视图将Identity列作为(代理)主键。它们还有一个“代码”字段,代表用户熟悉的唯一标识符。简单示例:CarModel:Id = 3,Code ='Ford'; 我已成功创建EF模式和OData以使用“代码”字段作为导航键进行导航,使用数据注释,并且基础表/视图在这些列上具有索引,因此这是可接受的。但我真的希望将Id列作为键,并将其作为模型中的导航属性,但不会将其显示在响应中。也许这就是OData部分有所作为的地方,因为我宁愿不做任何复杂的拦截和重新塑造响应。将列设置为“private”或甚至“internal”会在模型生成期间引发错误:“表X没有定义键”
是否可以在EF模型中定义标识列,但不能将其作为OData实体/响应的一部分?
修改
所以,我在下面的评论仍然有效。这对于标识/键列来说既不是一个好主意,也不会“隐藏”它们允许模型正确编译。但是,感谢来自@mreyeros的一些链接和来自Vitek Karas的social.msdn帖子,这里有一些注意事项。
System.Data.Services命名空间具有IgnorePropertiesAttribute
。它允许模型中的属性“隐藏”。但是,正如Vitek所说,它目前仅适用于ReflectionProvider,而不适用于EF。 (如果您使用的是NuGet托管版本,则需要确保引用正确的库。
也就是说,流畅的配置API 将在EF / OData中工作:
modelBuilder.Entity<Foo>().Ignore(f => f.Password);
但是,它不仅隐藏了响应中的属性,还将其隐藏在模型和数据库中(对于只读查询模型可能没问题)。因此,如果将导航键标记为隐藏,则模型将无法编译。如果您将任何其他属性标记为隐藏,但在QueryInterceptor中引用它,则会抛出异常。
答案 0 :(得分:0)
我不是100%确定是否是这种情况但是,如果您将“ScaffoldColumn(false)”属性应用于要隐藏的属性,它可能会起作用。以下是该属性的MSDN条目
答案 1 :(得分:0)
您需要做的是创建一个odata控制器,它返回原始实体的预计子集。
//in WebApi Config Method
config.MapHttpAttributeRoutes();
ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
builder.EntitySet<FullEntity>("FullData");
builder.EntitySet<SubsetEntity>("SubsetData");
config.Routes.MapODataServiceRoute("odata", "odata", builder.GetEdmModel());
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional, action = "GET" }
);
SetupJsonFormatters();
config.Filters.Add(new UncaughtErrorHandlingFilterAttribute());
...然后有一个用于FulLData的两个Odata控制器,一个用于SubsetData(具有不同的安全性),
namespace myapp.Web.OData.Controllers
{
public class SubsetDataController : ODataController
{
private readonly IWarehouseRepository<FullEntity> _fullRepository;
private readonly IUserRepository _userRepository;
public SubsetDataController(
IWarehouseRepository<fullEntity> fullRepository,
IUserRepository userRepository
)
{
_fullRepository = fullRepository;
_userRepository = userRepository;
}
public IQueryable<SubsetEntity> Get()
{
Object webHostHttpRequestContext = Request.Properties["MS_RequestContext"];
System.Security.Claims.ClaimsPrincipal principal =
(System.Security.Claims.ClaimsPrincipal)
webHostHttpRequestContext.GetType()
.GetProperty("Principal")
.GetValue(webHostHttpRequestContext, null);
if (!principal.Identity.IsAuthenticated)
throw new Exception("user is not authenticated cannot perform OData query");
//do security in here
//irrelevant but this just allows use of data by Word and Excel.
if (Request.Headers.Accept.Count == 0)
Request.Headers.Add("Accept", "application/atom+xml");
return _fullRepository.Query().Select( b=>
new SubsetDataListEntity
{
Id = b.Id,
bitofData = b.bitofData
}
} //end of query
} //end of class