这个linqTOsql自引用对象映射有什么问题?

时间:2010-09-09 21:43:25

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

我正在尝试使用linqTOsql映射创建自引用对象。到目前为止,我绝对是在我脑海里。这是我的代码:

[Table]
public class Category
{
    [Column(IsPrimaryKey=true, IsDbGenerated=true, AutoSync=AutoSync.OnInsert)]
    public Int64 catID { get; set; }
    public Int64 parentCatID { get; set; }
    public string catName { get; set; }
    public string catDescription { get; set; }

    internal EntityRef<IEnumerable<Category>> _category;
    [Association(ThisKey = "parentCatID", Storage = "_category")]
    public IEnumerable<Category> category {
        get { return _category.Entity; }
        set { _category.Entity = value; }
    }
}

我的fakeRepository定义如下:

// Fake hardcoded list of categories
private static IQueryable<Category> fakeCategories = new List<Category> {
    new Category { catID = 1, parentCatID = 0, catName = "Root", catDescription = "" },
    new Category { catID = 2, parentCatID = 1, catName = "Category w/subs", catDescription = "" },
    new Category { catID = 3, parentCatID = 1, catName = "Category no subs but now has subs", catDescription = "" },
    new Category { catID = 4, parentCatID = 2, catName = "Zub Cat", catDescription = "" },
    new Category { catID = 5, parentCatID = 2, catName = "Sub Cat", catDescription = "" },
    new Category { catID = 6, parentCatID = 0, catName = "Another Root", catDescription = "" },
    new Category { catID = 7, parentCatID = 0, catName = "Ze German Root", catDescription = "" },
    new Category { catID = 8, parentCatID = 3, catName = "Brand new cats", catDescription = "" },
    new Category { catID = 9, parentCatID = 8, catName = "Brand new cats sub", catDescription = "" },
}.AsQueryable();

我将Category传递给视图:

public ActionResult CategoryTree()
{
    IQueryable<Category> cats = genesisRepository.Category
                                                 .Where(x => x.parentCatID == 0)
                                                 .OrderBy(x => x.catName);
    return View(cats);
}

我遇到的问题是所有这些都会编译,但我没有得到超出根类别的任何内容。 Model[0].category返回null。

我的自引用对象出了什么问题?

修改

我想知道它是否无效,因为我的fakeRepository中没有真正的linq-to-sql数据上下文。如果是这样的话,还有办法解决吗?如果没有与数据库的连接,我可以让它工作吗?

2 个答案:

答案 0 :(得分:1)

是的,你的头部钉了一下。它不起作用,因为你使用的是假存储库。

Linq-to-Sql为您完成所有连接,并根据您在模型中设置的属性(及其属性)设置相关集合。

我不知道如何在没有数据库连接的情况下实现这一目标,因为internal EntityRef<IEnumerable<Category>> _category;对我来说完全陌生 - 我更像是POCO模型类型的人。

快速谷歌之后,我发现了这个 - How to: Map Database Relationships (LINQ to SQL)

您可以将模型更改为:

[Column(IsPrimaryKey=true, IsDbGenerated=true, AutoSync=AutoSync.OnInsert)]
public Int64 CatId { get; set; }
[Column]
public Int64 ParentCatId { get; set; }
[Column]
public string CatName { get; set; }
[Column]
public string CatDescription { get; set; }

private EntitySet<Category> _ChildCategories;
[Association(Storage = "_ChildCategories", OtherKey = "ParentCatId")]
public EntitySet<Category> ChildCategories
{
    get { return this._ChildCategories; }
    set { this._ChildCategories.Assign(value); }
}

private EntityRef<Category> _ParentCategory;
[Association(Storage = "_ParentCategory", ThisKey = "ParentCatId")]
public Category ParentCategory
{
    get { return this._ParentCategory.Entity; }
    set { this._ParentCategory.Entity = value; }
}

现在,因为您的ChildCategories属于EntitySet<Category>类型(继承自IList<T>),您应该能够自己连接虚假关系。

所以你可以这样做:

private static IQueryable<Category> GetFakeCategories()
{
    var categories = new List<Category> {
        new Category { CatId = 1, ParentCatId = 0, CatName = "Root", CatDescription = "" },
        new Category { CatId = 2, ParentCatId = 1, CatName = "Category w/subs", CatDescription = "" },
        //Blah
        new Category { CatId = 8, ParentCatId = 3, CatName = "Brand new cats", CatDescription = "" },
        new Category { CatId = 9, ParentCatId = 8, CatName = "Brand new cats sub", CatDescription = "" }
    };

    //Loop over the categories to fake the relationships
    foreach (var category in categories)
    {
        category.ChildCategories = new EntitySet<Category>(); //new up the collection
        foreach (var subLoopCategory in categories)
        {
            if (category.ParentCatId == subLoopCategory.CatId)
                category.ParentCategory = subLoopCategory;

            if (category.Id == subLoopCategory.ParentCatId)
                category.ChildCategories.Add(subLoopCategory);
        }
    }
    return categoies.AsQueryable();
}

至少在我脑海中起作用......: - )

HTHS,
查尔斯

编辑:回复:关于_childCategories上的空引用的评论如下。

您可以将模型更改为:

private EntitySet<Category> _ChildCategories = new EntitySet<Category>();

答案 1 :(得分:0)

它应该是null。你得到的所有类别的ParentId都是0 ...而且你没有Id为0的孩子。所以这对我来说似乎是正确的。

它没有显示任何子类别,因为它没有要显示的子类别。试试这个:

    IQueryable<Category> cats = genesisRepository.Category
                                                 .Where(x => x.parentCatID != 0)
                                                 .OrderBy(x => x.catName);

parentCatId需要指向有效的CatId才能将其作为子类别。此查询应该为您提供子类别的所有类别。