是否可以查询NotMapped属性?

时间:2018-10-23 15:33:45

标签: c# entity-framework entity-framework-6 ef-code-first ef-code-first-mapping

我首先使用EF6代码,我用this的答案在我的整个身体中映射了List<stirng>

这是我的课程

    [Key]
    public string SubRubro { get; set; } 
    [Column]        
    private string SubrubrosAbarcados
    {
        get
        {
            return ListaEspecifica == null || !ListaEspecifica.Any() ? null : JsonConvert.SerializeObject(ListaEspecifica);
        }
        set
        {
            if (string.IsNullOrWhiteSpace(value))
                ListaEspecifica.Clear();
            else
                ListaEspecifica = JsonConvert.DeserializeObject<List<string>>(value);                
        }
    }

    [NotMapped]
    public List<string> ListaEspecifica { get; set; } = new List<string>();

它非常适合以Json的身份存储我的列表,但是现在我需要执行linq查询,而我正在尝试这样做

var c = db.CategoriaAccesorios.Where(c => c.ListaEspecifica.Contains("Buc")).First();

它正在扔

  

System.NotSupportedException :指定的类型成员   LINQ to Entities不支持“ ListaEspecifica”。只要   初始化程序,实体成员和实体导航属性是   支持。

什么是合乎逻辑的。

有没有办法执行这样的查询?

2 个答案:

答案 0 :(得分:2)

这里的问题是LINQ to Entities无法理解如何将查询转换为后端(SQL)语言。因为您没有实现查询直到的结果(即转换为.NET),所以您对其进行过滤,因此LINQ尝试将查询转换为SQL本身。由于不确定如何执行此操作,因此您会得到NotSupportedException

如果首先实现查询(即调用.ToList()),然后进行过滤,则一切正常。我怀疑这不是您想要的。 (即db.CategoriaAccesorios.ToList().Where(c => c.ListaEspecifica.Contains("Buc")).First();

正如this answer所述,您的问题是EF到SQL的转换。显然,您需要某种解决方法。

因为您要进行JSON序列化,所以实际上这里有几个选项,尤其是使用LIKE

var c =
    (from category
     in db.CategoriaAccessorios
     where SqlMethods.Like(c.SubrubrosAbarcados, "%\"Buc\"%")
     select category).First()

如果是EF Core,则据称Microsoft.EntityFrameworkCore.EF.Functions.Like应该替换SqlMethods.Like

如果您拥有SQL Server 2016+,并且将SubrubrosAbarcados强制为JSON类型,则应该可以使用原始查询直接直接查询JSON列。

如果您对上述方面感到好奇,请查看以下示例,了解它在SQL Server 2016中的外观:

CREATE TABLE Test (JsonData NVARCHAR(MAX))
INSERT INTO Test (JsonData) VALUES ('["Test"]'), ('["Something"]')
SELECT * FROM Test CROSS APPLY OPENJSON(JsonData, '$') WITH (Value VARCHAR(100) '$') AS n WHERE n.Value = 'Test'
DROP TABLE Test

答案 1 :(得分:1)

我能够通过CompiledExpression做这样的事情。

using Microsoft.Linq.Translations;

// (...) namespace, class, etc

private static readonly CompiledExpression<MyClass, List<string>> _myExpression = DefaultTranslationOf<MyClass>
    .Property(x => x.MyProperty)
    .Is(x => new List<string>());

[NotMapped]
public List<string> MyProperty
{
    get { return _myExpression.Evaluate(this); }
}

我希望有更好/更漂亮的解决方案;)