【问题标题】:asp.NET MVC 3 Composite pattern model bindingasp.NET MVC 3 复合模式模型绑定
【发布时间】:2012-08-01 19:12:43
【问题描述】:

我的应用程序有产品和供应商,并且它们在“具有”关系中都有相似的项目......特别是它们有一个“收藏夹”,因此用户可以为它们添加书签。

所以我们有:

public class Product
{
    public int ProductId {get;set;}
    public int Name {get;set;}
    public List<Favorite> Favorites {get;set;}
}

public class Vendor
{
    public int VendorId {get;set;}
    public int Name {get;set;}
    public List<Favorite> Favorites {get;set;}
}

public class Favorite
{
    public int FavoriteId {get;set;}
    public string UserName {get;set;}
}

起初这不起作用,所以我补充说:

    public int? VendorId {get;set;}
    public int? ProductId {get;set;}

现在我遇到的问题是我的 Vendor.Favorites 和 Product.Favorites 始终为空。

我如何绑定这些以便我可以使用这样的对象?我不让它成为一个单独的实体吗?

谢谢!

更新:我应该注意到我正在使用 MVC 3 Code-first 和 POCO。

更新:解决方案:

我认为这并不理想,仍在解决我希望它如何工作的问题,因为它会添加冗余代码来添加收藏夹和评论。

public class Product
{
    public int ProductId {get;set;}
    public int Name {get;set;}
    public virtual List<Favorite> Favorites {get;set;}
}

public class Vendor
{
    public int VendorId {get;set;}
    public int Name {get;set;}
    public virtual List<Favorite> Favorites {get;set;}
}

在收藏夹类中使用原始的可为空的 int 变量使其工作,但如果我想将收藏夹类与其他对象一起使用,我将不得不修改收藏夹属性,使用到对象键的新映射。出于好奇,在正常处理这些类时,您如何管理这些对象的数据存储?我假设你在 DAL 处理它?

【问题讨论】:

    标签: asp.net-mvc-3 ef-code-first model-binding composite


    【解决方案1】:

    您可以使用继承,创建一个仅包含收藏夹的基类,然后基于该基类派生其他信息的类。这建立了“是”关系

    例如

    public class baseClass
    {
     public list<Favorite> Favorites { get; set;}
    }
    public class Product : base
    {
     public int ProductID { get; set; }
     public string Name { get; set; }
    }
    

    然后一个产品对象将具有所有 3 个属性。

    【讨论】:

    • 然后我可以在基类中有其他共享的部分,如评论和 cmets?我会考虑这个变化。你用过这种风格吗?您是否需要做任何特别的事情才能将数据导入实体?
    • 是的,你放在基类中的任何东西都可以被任何派生对象使用,就好像它是该对象类的属性一样,它是完全透明和动态的(你可以在类型之间转换并保持通用数据。)我在使用 2 个可能仅在一个领域不同的非常相似的项目时使用了这种风格。例如,在我处理零件和包的工作项目中,除了“包号”/“零件号”字段外,它们是相同的。除了那些字段之外的所有字段都进入一个基类,然后“packagenumber”/“partnumber”分别进入 package 和 part 类。
    • 数据库如何区分不同的类?它有单独的表格吗?
    【解决方案2】:

    基于您使用的是 EF 4.1 的假设:

    你的模型看起来很不错,除非我会改变

        public int? VendorId {get;set;}
        public int? ProductId {get;set;}
    

        public virtual Vendor VendorId {get;set;}
        public virtual Product ProductId {get;set;}
    

    那么你的 FK 关系应该已经设置好了。根据我对 EF 的理解,List&lt;Favorite&gt; 旨在建立关系,实际上并未填充。您必须自己填充它,方法是在上下文中调用 .Include() 或引用 EF 在数据库中创建的实际 FK,在您的情况下为 VendorId_FavoriteIdProductId_FavoriteId

    【讨论】:

    • 这最终是倒退,但让我在正确的地方。我需要 int?'s 以便应用程序可以具有原始映射并且没有循环引用(糟糕),我将公共列表 更改为公共虚拟列表,每个人都很高兴
    【解决方案3】:

    我会保留一个属性来存储 ID(VendorID 或 ProductId)并使用另一个属性来告诉我它是什么类型(VendorProduct

    public class Favorite
    {
        public int FavoriteId {get;set;}
        public string UserName {get;set;}
        public int ItemID { set;get;}    //can use a better generic name
        public FavoriteType Type { set;get;}
    }
    

    我有一个 Enum 用于类型

    public enum FavoriteType
    {
        Vendor, 
        Product
    }
    

    并确保在访问它们之前初始化子属性/对它们应用方法,这样它就不会抛出空引用异常!。你可以自己做构造函数

    public class Product
    {
        public int ProductId {get;set;}
        public int Name {get;set;}
        public List<Favorite> Favorites {get;set;}
    
      public Product()
      {
          if(Favourites==null)
              Favorites=new List<Favorite>();
      }
    }
    

    【讨论】:

    • 无论我使用可空外键还是鉴别器字段,它仍然不是 100% 可扩展的,但我可以接受。所以我初始化了列表,我应该填写它还是 MVC3 会为我做呢?
    • 我不同意 FavoriteType 枚举。收藏夹不应该知道它的类型。这可能会破坏 Liskov 替换原则。检索收藏夹的上下文将确定收藏夹类型。同样在 Product 构造函数中,它可以转换为 null coalesce Favorites ?? new List&lt;Favorite&gt;()
    • 我添加了 null 构造函数并再次尝试使用。我检查了数据库,它在收藏夹表中的项目与产品表中的项目相匹配。当我提到该产品的最爱时,它说 0 count.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多