4

我是Linq的新手。我一直在使用强类型数据集,但喜欢 Linq 创建对象的想法。

目前,我使用数据集来检索连接来自 tblProducts 和 tblProductSettings 的数据的表。

这是一对多的关系,因为产品服务于多个网站,每个网站都有一个唯一的 tblSettings 行,但是它假设每个网站总是有一行 tblSettings。

例子 :

Select * from tblproducts, tblProductSettings where tblproducts.ProdID = tblProductSettings.ProdID and tblProductSettings.CreatorID = @CreatorID

数据集将提供一个很好的表格来循环并显示带有设置的产品。

Linq 会给我一个带有 tblProductSettings 作为集合的 tblProducts 对象。我不想每次都循环一个集合来获取设置,我相信为每个产品创建一个新的 sql 查询并使访问设置变得痛苦。

我可以创建一个自定义对象 tblProductsAll,但我可以填充这个对象的唯一方法是......

var Product = from p in context.tblProducts
              join ps in context.tblProductSettings on p.ProdID equals ps.ProdID
              where p.CreatorID == 1 && ps.ProdCreatorDisplay == 1
              select new tblProductsAll() 
              { 
                   ProdTitle = p.ProdTitle,
                   ProdPrice = ps.ProdPrice
              };

然后我可以将此模型传递给剃刀模板。

我的问题是......有没有更好的方法来设置属性?有 20 个或更多不同的属性,我不想每次都在站点中使用具有不同 where 子句的相同对象时不断设置它们,重复代码。有没有办法阻止这种重复?即自动映射对象,或重用select new 语句。

任何帮助将非常感激。

4

2 回答 2

0

由于您已标记此,我猜您正在使用实体框架。在这种情况下,您可以告诉 linq 它为您的产品加载设置,而无需明确指定连接。我在这里假设您的产品与您的产品设置表有关系,该表通过您的产品实体上的 Settings 属性公开。

var allProducts = context.tblProducts
    .Where(p => p.CreatorID == 1 && p.Settings.ProdCreatorDisplay == 1)
    .Include(p = p.Settings)
    .Select(p => CreateViewModelFromFullyPopulatedProductModel(p))
    .ToList();

一旦你加载了完整的设置,你就可以编写一个映射函数来为你做映射。当然,这将加载产品的所有属性以及每个产品的设置。这可能是一个主要问题,具体取决于您正在加载多少产品以及它们有多少未使用的属性,但从您的问题来看,听起来您已经为视图模型加载了大部分这些值。

于 2012-11-30T16:24:49.987 回答
0

当有导航属性时,使用它们!您的Product实体有一个导航属性ProductSettings。这意味着查询可能如下所示:

var products = from p in context.Products
               from ps in p.ProductSettings
               where p.CreatorID == 1 && ps.ProdCreatorDisplay == 1
               select new ProductsAll() 
               { 
                    ProdTitle = p.ProdTitle,
                    ProdPrice = ps.FirstOrDefault().ProdPrice
               };

(请注意,我固执地拒绝使用tbl前缀)

但这并不能解决重复代码问题。

输入自动映射器。这是一个不错的小工具,它通过定义和执行对象之间的映射来从代码中删除样板属性复制语句。默认映射基于名称约定。例如,该语句配置和Mapper.CreateMap<Product,ProductDto>();的所有同名属性之间的映射。并且会从.ProductProductDtoMapper.Map<ProductDto>(product);ProductDtoproduct

但是您的ProductsAll班级有一个ProdPrice来自ProductSettings. 如何处理?

这里可以使用 AutoMapper 的一个不错的功能。它还根据名称约定解析嵌套对象的属性。假设您的类Product有一个属性Title,AutoMapper 可以将其解析为ProductTitle目标对象中的属性。让我们使用它:

class ProductsAll
{
    // ProductSetting should have a Product property.
    public string ProductTitle { get; set; }
    // Assuming ProductSetting has a property ProdPrice.
    public decimal ProdPrice { get; set; }
}

...

Mapper.CreateMap<ProductSetting,ProductsAll>(); // ProductSetting!

var q = from ps in context.ProductSettings
        where ps.Product.CreatorID == 1 && ps.ProdCreatorDisplay == 1;

// Now the magic!
var products = q.Project().To<ProductsAll>();

Project()是 . 上的扩展方法IQueryable。好处是 SQL 语句只包含投影中使用的属性。如您所见,您可以定义一次映射,其余的使用Project().To()代码中的构造。

AutoMapper 还有更多功能。这是一个快速的开始。

于 2012-12-02T10:16:57.510 回答