实体框架预计专栏

时间:2018-10-04 09:52:36

标签: c# entity-framework asp.net-core-2.0

我希望将实体集合作为OData提要公开,仅用于查询。我遇到的问题是,公开的数据类型与数据库上的一对一不匹配。例如。

我的实体上有一个MaterialId的财产,但这是由MATERIAL + MATERIAL_GRP_1

组成的

在EF .net core2.1中是否可以做到这一点

我尝试使用

entity.Property(p => p.MaterialId).HasComputedColumnSql("[MATERIAL] + '-' + [MATERIAL_GROUP_1]");

但是,当我查询该实体时,数据库上生成的SQL正在寻找$it.MaterialId,但由于数据库表中没有这样的列而失败了。

有没有办法解决这个问题?

2 个答案:

答案 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将在本地进程上执行。

AsEnumerable

让我们首先描述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和一个ExpressionProvider代表必须执行的查询。 Expression知道谁必须执行查询(哪个DBMS),知道如何将Provider转换为查询的执行者(SQL)的语言,并且知道如何与执行者进行通信。

要枚举Expression时,可以隐式使用IQueryableforeachToList()FirstOrDefault()等,或显式使用{{ 1}}和Max(),则GetEnumerator发送到MoveNext

ExpressionProvider转换为DBMS理解并执行查询的语言。结果被转换为IEnumerable,其中ProviderExpression被称为

问题是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()。