可以查询 NotMapped 属性 吗?
It is possible to query a NotMapped property?
我首先使用 EF6 代码,然后我使用 this 答案在我的实体中映射 List<stirng>
。
这是我的class
[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: The specified type member
'ListaEspecifica' is not supported in LINQ to Entities. Only
initializers, entity members, and entity navigation properties are
supported.
什么是合乎逻辑的。
有什么方法可以执行这样的查询吗?
这里的问题是 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 类型,应该可以使用原始查询直接查询 [=特别是 39=] 列。
如果您对上述方面感到好奇,这里是 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
我可以通过 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); }
}
不过我希望有更好/更漂亮的解决方案 ;)
我首先使用 EF6 代码,然后我使用 this 答案在我的实体中映射 List<stirng>
。
这是我的class
[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: The specified type member 'ListaEspecifica' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
什么是合乎逻辑的。
有什么方法可以执行这样的查询吗?
这里的问题是 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 类型,应该可以使用原始查询直接查询 [=特别是 39=] 列。
如果您对上述方面感到好奇,这里是 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
我可以通过 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); }
}
不过我希望有更好/更漂亮的解决方案 ;)