【问题标题】:Use a NotMapped property value with Odata $filter function将 NotMapped 属性值与 Odata $filter 函数一起使用
【发布时间】:2017-07-11 02:33:50
【问题描述】:

我正在尝试弄清楚如何将 NotMapped 属性与 OData 一起使用

我有这个用户模型

[DataContract]
public class User
{
[DataMember]
public long Id { get; set; }
[DataMember]
public virtual InstagramUser InstagramUser { get; set; }
[DataMember]
public virtual FacebookUser FacebookUser { get; set; }
[NotMapped]
public string InstagramID { get; set; 
}

我在用户控制器中有这个 GetAll() 方法

public IQueryable<User> GetAllUsers()
{
       _repository = new UserRepository();
       return _repository.GetAll().AsQueryable();
 }

以及用户存储库中的这个 GetAll() 函数

public IQueryable<User> GetAll()
{
     InstaStoryDB db = new InstaStoryDB();
     var ret = db.Users.Include("InstagramUser").Include("FacebookUser").AsQueryable();
     foreach(User user in ret)
     {
        user.InstagramID = user.InstagramUser.InstagramID; //<-- I'm adding here the value to the property
     }
     return ret;         
}

这就是 Instagram 用户模型

[DataContract]
public class InstagramUser
{
[DataMember]
public long UserId { get; set; }
[DataMember]
public string InstagramID { get; set; 
}

一切正常。

我对 User 模型进行了更改并添加了包含 InstagramIDInstagramUser,因此我添加了 [NotMapped] 属性以从 DB 中的 User 表中删除 InstagramID,因为InstagramUser 已经包含 InstagramID。

当我尝试像这样使用 Odata 时: localhost:555/api/users/?$filter=InstagramID eq '456456546' 失败并返回 InstagramID 属性不存在的错误。

如何在 NotMapped 属性上使用带有 Odata 的过滤器?

【问题讨论】:

  • 我猜你不能使用NotMapped 属性。 NotMappet 属性未在您的模型中描述,因此当您将 EF 提供程序用于 OData 服务时,它不可用于查询。
  • 这就是我的想法,我在问题中添加了一个修复.. 你现在可以看一下吗?

标签: asp.net-mvc entity-framework odata


【解决方案1】:

这对我在 Web API 中使用 OData v4 有效:

var t = modelBuilder.StructuralTypes.First(x => x.ClrType == typeof(User));
t.AddProperty(typeof(User).GetProperty("InstagramID"));

【讨论】:

  • 这对我有用。我在每个实体上都有一个未映射的仅获取详细信息属性,我将不同的属性格式化为字符串。现在 OData 将它们包含在响应中。
【解决方案2】:

您可以在此处找到修复程序:http://forums.asp.net/t/1887669.aspx?OData+EF+Model+with+custom+calculated+properties

  1. 首先手动处理 odata 查询
  2. 使用选择查询添加未映射的属性

例如

public IQueryable<DomainModel> GetAllDomains(ODataQueryOptions<Domains> queryOptions)
    {
        var query = queryOptions.ApplyTo(objectContext.Domains) as IQueryable<Domain>;
        return query.AsEnumerable().Select(d => new DomainModel
        {
            Name = d.Name,
            Activated = d.Activated,
            Address = d.Address,
            AdminUserName = d.AdminUserName,
            DateCreated = d.DateCreated,
            Enabled = d.Enabled,
            Subscription = (SubscriptionTypes)d.SubscriptionType,
            Website = d.Website,
            StatsUpdatePending = d.StatsUpdatePending,
            LastHousekeeping = d.LastHousekeeping,
            CalculatedProperty = calculator.Calculate(d.Name, d.Activated)
        }).AsQueryable();
    }

【讨论】:

  • 谢谢伙计,但已经 2 年了,我没有选择检查这个解决方案的选项。我会为你的时间投票 :) 谢谢!
  • 没问题,我只是看到那里没有答案...所以,这总比没有好:p
  • 如果你尝试通过 $filter=contains(CalculatedProperty, 'x') 你会得到异常:The specified type member 'CalculatedProperty' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
  • 那你没有做: AsEnumerable() 因为 AsEnumerable() 将它转换为 Linq To Objects 而不是 Linq to Entities。如果我没记错(已经 > 3 年),则查询未应用于 NotMapped 属性。它是 Enumerable(),或者在 odata 版本之间发生了变化。
【解决方案3】:

我找到了一个与 Jason Steele 类似的解决方案,但使用的方法 EntityType 和 Property 如下:

modelBuilder.EntityType<User>().Property(u => u.InstagramID);

结果是一样的。如果你看一下Property方法的源码,你会发现它是在获取PropertyInfo,然后将其添加到该类的StructuralTypeConfiguration中:

PropertyInfo propertyInfo = PropertySelectorVisitor.GetSelectedProperty(propertyExpression);
PrimitivePropertyConfiguration property = _configuration.AddProperty(propertyInfo);

【讨论】:

    猜你喜欢
    • 2017-05-20
    • 2012-11-21
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多