如何使用LINQ To SQL查询填充对象的子List属性

时间:2010-11-09 12:21:52

标签: c# linq linq-to-sql asp.net-mvc-2 poco

我正在为在线商店创建产品列表。这是非常标准的东西,产品缩略图页面,包含简要的细节,价格和完整细节的链接。

我正在使用存储库模式,因此我有一个中央数据存储库,它从SQL服务器返回表。为了简洁起见,我已经删除了很多代码,但只是让你明白了:

public class SqlProductsRepository : IProductsRepository
{
    private Table<Product> productsTable;

    public SqlProductsRepository(string connectionString)
    {
        var context = new DataContext(connectionString);

        productsTable = context.GetTable<Product>();
        // More tables set up here
    }

    public IQueryable<Product> Products
    {
        get { return productsTable; }
    }

    // More properties here
}

我将以下对象映射到表:

[Table(Name = "Products")]
public class Product
{
    [Column(IsPrimaryKey = true)]
    public string ProductCode { get; set; }
    [Column]
    public string Name { get; set; }
    [Column]
    public decimal Price { get; set; }

    public List<ShopImage> Images = new List<ShopImage>();
}

[Table(Name = "Images_Products")]
public class Image_Product
{
    [Column] 
    public int ImageID { get; set; }
    [Column] 
    public string ProductCode { get; set; }
    [Column] 
    public int DisplayOrder { get; set; }
}

[Table(Name = "Images")]
public class Image
{
    [Column(Name = "ImageID")]
    public int ImageID { get; set; }
    [Column]
    public bool Caption { get; set; }
}

如果我执行以下查询:

// 'db' is the repository (member variable of the controller class)

IQueryable<Product> products = from p in db.Products
                               join ip in db.Image_Product on p.ProductCode equals ip.ProductCode
                               where ip.DisplayOrder == 0
                               select p;

我得到了一个很好的IQueryableProduct个对象。但是,我想要做的事情是使用单个Images对象填充每个对象的Image列表属性,并从已加入的Image_Product表中设置其ID。

所以我最终得到一个Products列表,每个Image属性中都有一个Images,其中包含DisplayOrder所在数据库中该产品的图像ID 0

我尝试了这个投影,我觉得这很有道理:

IQueryable<Product> products = from p in db.Products
                               join ip in db.Image_Product on p.ProductCode equals ip.ProductCode
                               where ip.DisplayOrder == 0
                               select new Product { 
                                    ProductCode = p.ProductCode,
                                    Price = p.Price,
                                    Images = new List<Image> { 
                                        new Image { ImageID = ip.ImageID } 
                                    }
                               };

编译但会引发运行时错误:Explicit construction of entity type 'xxx.Product' in query is not allowed.

在项目的其他地方,我这样做:

var pages = from i in db.TemplatePageNavigationItems
            orderby i.DisplayOrder
            select new NavigationItem {
                ID = i.PageID,
                ParentID = i.ParentID,
                Text = i.Name,
                Title = i.Name,
                Url = (i.Folder == null) ? "" : i.Folder
            };

不要抱怨!我认为这与第一个返回IQueryable<Product>的查询有关,但我不确定原因。

真的有两个问题:为什么在第一种情况下不允许这样做,为了得到我想要的结果,应该做什么?

1 个答案:

答案 0 :(得分:1)

正如错误所述,您无法在查询中构造显式实体类型(Product就是这样),应返回IQueryable<Product>。您的pages查询将返回IEnumerable<NavigationItem>,而NavigationItem似乎不是数据库中定义的实体类型。

您可以尝试在第一个查询中返回IEnumerable<Product>,或者定义一个单独的类型,然后返回IEnumerable,如果您需要投影一个明确的,自定义的对象实例。