简体   繁体   English

EntityFramework自定义SQL查询的虚拟属性

[英]EntityFramework custom sql query on virtual property

We use 6.1.2 EF and we have edmx generated from database. 我们使用6.1.2 EF,并且已经从数据库生成了edmx。

We have POCO class like: 我们有POCO类,例如:

public partial class Category
{
    public Category()
    {
        this.Products = new HashSet<Product>();
    }

    public long CategoryID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

What I need to do, is insert new virtual property with custom sql query calling like: 我需要做的是使用如下自定义sql查询插入新的虚拟属性:

public virtual int ProductsCount { get; set; }

which will return select count(1) from dbo.Product where CatgoryID = *** Is it possible to define virtual property like this? 它将select count(1) from dbo.Product where CatgoryID = ***返回select count(1) from dbo.Product where CatgoryID = ***是否可以这样定义虚拟属性? I find some sql query definitions in .edmx xml file, so I hope, there can be defined mine too. 我在.edmx xml文件中找到了一些sql查询定义,所以我希望也可以定义我的。 What can I replace the *** with? 我可以用什么代替***?

After all, my code should be called as simple as: 毕竟,我的代码应该简单地称为:

context
    .Category
    .Include(x => x.ProductsCount)
    .ToList();

Messing with the generated XML is genrally not a good idea. 通常,处理生成的XML并不是一个好主意。 Any regeneration will override your code. 任何重新生成都会覆盖您的代码。

IMO, your property shall look like : IMO,您的财产应如下所示:

public int ProductCount { get { return Products.Count(); } }

And your request should be : 您的要求应该是:

context.Category.Include(x => x.Products).ToList();

If loading the full products list might lead to problems, I would use a DB View ot the Category table with a computed column and then update my EF mapping to have this new entity inherit the Category entity. 如果加载完整的产品列表可能会导致问题,我将使用带有已计算列的类别表的数据库视图,然后更新我的EF映射,以使此新实体继承类别实体。

If Entity Framework had formula properties, like NHibernate, this could be a viable option. 如果Entity Framework具有公式属性,例如NHibernate,则这可能是一个可行的选择。 However, with Entity Framework you can't do this without breaking persistence ignorance and generating n + 1 queries. 但是,使用Entity Framework,您不能不破坏持久性的无知并生成n + 1个查询。

  • Persistence ignorance: entities are not supposed to have any reference to the data layer that created them. 持久性无知:实体不应该引用创建它们的数据层。 This is an important proposition that shouldn't be broken. 这是一个重要的主张,不应被打破。 Else you create a situation in which it is hard to track (and to predict) when and where queries will be executed. 否则,您将很难跟踪(预测)何时何地执行查询。 Moreover, it breaks the single responsibility principle. 而且,它打破了单一责任原则。

  • n + 1 anti pattern: other than NHibernate with formula properties, EF won't be able to integrate the embedded query in the query it executes to fetch Category s from the database (1). n + 1反模式:除具有公式属性的NHibernate之外,EF将无法将嵌入式查询集成到它从数据库中获取Category的查询中(1)。 Each category will subsequently execute its own query (n). 每个类别随后将执行其自己的查询(n)。

The best way to do this is project the data to a view model (or DTO class, whichever name suits you best): 最好的方法是将数据投影到视图模型(或DTO类,以最适合您的名字):

context.Categories.Select(c => new CategoryModel
{
    Name = c.Name,
    OtherProperty = c.OtherProperty,
    ProductsCount = c.Products.Count()
}

When it comes to projections you should always look at what AutoMapper can do for you. 当涉及投影时,您应该始终查看AutoMapper可以为您做什么。 If you have this CategoryModel class you can define a mapping once (at application startup)... 如果您具有CategoryModel类,则可以定义一次映射(在应用程序启动时)。

Mapper.CreateMap<Catecory,CategoryModel>();

...and use it like so: ...并像这样使用它:

context.Categories.Project().To<CategoryModel>();

The nice thing of AutoMapper is that it parses a property like ProductsCount into a property in the source class, Products , and the operation working on it, Count() . AutoMapper的好处是,它将ProductsCount之类的属性解析为源类Products的属性,并将该类上的操作Count()解析为属性。 This single line of code does exactly the same thing as the previous code snippet. 这一行代码与上一个代码段完全相同。

Side note: likewise, AutoMapper parses nested properties. 旁注:同样,AutoMapper解析嵌套属性。 A property CategoryName you might have in a ProductModel class (if Product-Category is n-1) would resolve to product.Category.Name . 您可能在ProductModel类中拥有的CategoryName属性(如果Product-Category为n-1)将解析为product.Category.Name

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM