我希望将实体集合作为OData提要公开,仅用于查询。我遇到的问题是,公开的数据类型与数据库上的一对一不匹配。例如。
我的实体上有一个MaterialId
的财产,但这是由MATERIAL
+ MATERIAL_GRP_1
在EF .net core2.1中是否可以做到这一点
我尝试使用
entity.Property(p => p.MaterialId).HasComputedColumnSql("[MATERIAL] + '-' + [MATERIAL_GROUP_1]");
但是,当我查询该实体时,数据库上生成的SQL正在寻找$it.MaterialId
,但由于数据库表中没有这样的列而失败了。
有没有办法解决这个问题?
答案 0 :(得分:0)
我推荐其他方式
public class Contact
{
public string MATERIAL { get; set; }
public string MATERIAL_GROUP_1 { get; set; }
[NotMapped]
public string MaterialId => $"{MATERIAL} {MATERIAL_GROUP_1}";
}
答案 1 :(得分:0)
因此,您有一个entities
序列,其中每个entity
都有一些属性。您要从此序列中选择几个(或全部)项目,并将每个entity
转换为相似类的对象。为此,我们使用Select
我不确定您的序列是AsEnumerable
还是AsQueryable
。区别在于IQueryable
将在不同的进程(通常是数据库)上执行,而IEnumerable
将在本地进程上执行。
让我们首先描述IEnumerable
。假设您的输入序列是Persons
的序列,而您的输出是SimplePersons
的序列。尽管它们看起来很相似,但还是有细微差别
class Person
{
public int Id {get; set;}
public string FirstName {get; set;}
public string LastName {get; set;}
}
class SimplePerson
{
public int Id {get; set;}
public string FullName {get; set;}
}
假设您有一系列的人物,并且想要将它们转换为一系列的SimplePersons:每个Person
应该成为一个SimplePerson
,其中FullName
是人物的{ {1}}和FirstName
。
使用“选择LastName
人员to project every
SimplePerson`:
into a
Voila!简单的漫画卓悦!
如果输入的人员序列为IEnumerable<Person> persons = ...
IEnumerable<SimplePerson> simplePersons = persons
// convert every Person into a SimplePerson:
.Select(person => new SimplePerson()
{
Id = person.Id,
FullName = person.FirstName + " " + person.LastName,
});
,则通常必须通过不同的过程来执行查询。这通常是一个数据库管理系统。 AsQueryable
有一个IQueryable
和一个Expression
。 Provider
代表必须执行的查询。 Expression
知道谁必须执行查询(哪个DBMS),知道如何将Provider
转换为查询的执行者(SQL)的语言,并且知道如何与执行者进行通信。
要枚举Expression
时,可以隐式使用IQueryable
,foreach
,ToList()
,FirstOrDefault()
等,或显式使用{{ 1}}和Max()
,则GetEnumerator
发送到MoveNext
。
Expression
将Provider
转换为DBMS理解并执行查询的语言。结果被转换为IEnumerable,其中Provider
和Expression
被称为
问题是SQL不知道您的GetEnumerator
,因此无法调用其构造函数。
一种解决方案是在将MoveNext
投影到SimplePerson
之前调用ToList()
:
Persons
但是,如果您不想使用所有simplePerson,这将是浪费或处理能力:
SimplePersons
首先,您获取了所有1000个人,然后仅检查是否至少有一个IEnumerable<SimplePerson> FetchSimplePersons()
{
IQueryable<Person> persons = ...
IEnumerable<SimplePerson> simplePersons = simplePersons
// execute the query, move persons to local process
.ToList()
// convert every Person into a SimplePerson:
.Select(person => new SimplePerson()
{
Id = person.Id,
FullName = person.FirstName + " " + person.LastName,
});
return simplePersons;
}
。多么浪费处理能力!
为此发明了bool personsAvailable = FetchSimplePersons().Any()
。该函数以一种智能的方式获取可查询的数据,因此,如果您不使用所有获取的数据,则浪费不会太大。有几种策略可以限制损失。每个SimplePerson
实际使用的策略都不同。
AsEnumerable()
常用的策略是每页获取Provider
,例如100 AsEnumerable
。如果仅使用其中的几个,则将丢弃页面上所有其他提取的Persons
,但至少比丢弃所有1000 Persons
Persons
如果在当前页面的最后一项调用Persons
,则 IEnumerable<SimplePerson> FetchSimplePersons()
{
IQueryable<Person> persons = ...
IEnumerable<SimplePerson> simplePersons = simplePersons
// execute the query per page:
.AsEnumerable()
// convert every fetched Person into a SimplePerson:
.Select(person => new SimplePerson()
{
Id = person.Id,
FullName = person.FirstName + " " + person.LastName,
});
return simplePersons;
}
足够聪明以获取下一页。因此对于用户来说,它类似于ToList()。