0

这确实是一个 EF Code First 问题,但有时 OData 的上下文会有所不同。问题很简单。我们的基础 SQL Server 表/视图将标识列作为(代理)主键。它们还有一个“代码”字段,代表用户熟悉的唯一标识符。简单示例: CarModel: Id = 3, Code = 'Ford'; 我已成功创建 EF 模式和 OData 以使用“代码”字段作为导航键进行导航,使用数据注释,并且基础表/视图在这些列上有索引,因此这是可以接受的。但我真的很想将 Id 列作为键,并作为模型中的导航属性,但不让它显示在响应中。也许这就是 OData 部分有所作为的地方,因为我不希望对响应进行任何复杂的拦截和重塑。将列设置为“私有”甚至“内部”会在模型生成期间引发错误:“表 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 中引用它,则会引发异常。

4

2 回答 2

2

您需要做的是创建一个返回原始实体的投影子集的 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());

...然后有两个 Odata 控制器,一个用于 FulLData,一个用于 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
于 2016-05-11T17:23:19.643 回答
0

我不是 100% 确定是否是这种情况,但是,如果将“ScaffoldColumn(false)”属性应用于要隐藏的属性,它可能会起作用。这是该属性的MSDN条目

于 2012-08-07T17:40:34.460 回答