2013-04-11 179 views
1

我不能環繞這個問題我的腦海裏,並沒有找到正確的搜索鑰匙了:添加動態屬性模型

我想有幾個itemscategories所有items有具體attributes 。那些attributes(文本字段,下拉列表或複選框)應該被添加到category,我想編輯並保存那些attributes爲每個item

我正在使用MVC 4和代碼優先的EF5。我怎樣才能實現這個?

我的第一種方法是幾類,如Text,從抽象Attribute類繼承的DropdownCategory類是這樣的:

public class Category 
{ 
    [Key] 
    public int CategoryId { get; set; } 

    public string Name { get; set; } 
    public string Description { get; set; } 

    public virtual ICollection<Item> Items { get; set; } 
    public virtual ICollection<Attribute> Attributes { get; set; } 
} 

但後來我不知道繼續。我是對的還是完全錯了?有人能給我一些我可以搜索的提示嗎?

編輯

最終我試圖建立的HiFi設備的列表。揚聲器與放大器有不同的屬性,對錄音機有不同的屬性。我想統一瞭解每個設備的詳細信息,並預先定義該類別的特定屬性,並附加一個免費的全文文本區域。揚聲器XYZ是我的item,揚聲器我的category和dB和attribute

+0

我是唯一一個不理解你的問題的人嗎?我不太明白什麼是屬性或什麼是項目或彼此之間以及與類別之間的關係 – Fendy 2013-04-11 13:19:28

+0

@芬迪:我編輯了我的問題,這是否更清楚? – Sven 2013-04-11 13:33:29

+0

我試圖回答它。希望我的理解足夠好。 – Fendy 2013-04-11 13:54:37

回答

1

我其實從來沒有使用代碼優先的方法,但我可以給你一些關於如何處理這種情況的想法...對我來說,它看起來Item是主要的而不是Category。所以,你可以有這樣的結構......

public class Category 
{ 
    [Key] 
    public int CategoryId { get; set; } 
    public string CategoryName { get; set; } 
    public string CategoryDescription { get; set; } 
    // use attributes here if you want them for Category 
    //public Dictionary<string, string> ItemnAttributes { get; set; } 
} 

public class MyItem 
{ 
    [Key] 
    public int ItemId { get; set; } 
    public string ItemName { get; set; } 
    public string ItemDescription { get; set; } 
    public Category ItemnCatagory { get; set; } 
    public Dictionary<string, string> ItemnAttributes { get; set; } 
} 

希望這有助於..

+0

但是,然後屬性被分配給每個項目,而不是一個類別。爲現有類別創建新項目意味着複製來自同一類別中另一項目的屬性,不是嗎? – Sven 2013-04-11 13:19:00

+0

因爲你在第二行中提到'所有項目都有特定的屬性',但是如果你想與類別建立屬性,只需將該屬性放在'Category'中並從'MyItem'中移除即可.. – 2013-04-11 13:28:23

+0

嘿,我製作了一個混亂...我認爲使用「字典<字符串,字符串>」爲您的屬性是足夠的,而不是「列表<字典<字符串,字符串>>」... ... – 2013-04-12 12:19:03

1

好了,所以這個問題基本上是關於數據的設計。

首先,我認爲規則是:

  1. 一個項目都有一個類別
  2. 一類具有許多屬性
  3. 一個項目與類別

相關的許多屬性對於規則1,在你的設計中已經足夠了。 (簡單例子)

public class Category{ 
    public IEnumerable<Item> Items{get;set;} 
} 
public class Item{ 
    public Category Category{get;set;} 
} 

它足夠清楚。

對於規則no.2,我認爲你應該做一個CategoryAttribute類。它擁有一個到多個類別和屬性之間的關係。基本上,CategoryAttribute是一個主,而孩子將是ItemAttribute。

public class Category{ 
    public IEnumerable<CategoryAttribute> CategoryAttributes{get;set;} 
} 
public class CategoryAttribute{ 
    public Category Category{get;set;} 
    public string CategoryName{get;set;} 
    public string DefaultValue{get;set;} // maybe a default value for specific 
             // attribute, but it's up to you 

    public IEnumerable<ItemAttribute> ItemAttributes{get;set;} 
} 

IEnumerable<ItemAttribute>是category屬性和item屬性之間的一對多關係。

對於規則no.3,規則no.2中描述的ItemAttribute將表示屬性由每個項目擁有。

public class Item{ 
    public IEnumerable<ItemAttribute> ItemAttributes{get;set;} 
} 
public class ItemAttribute{ 
    public Item Item {get;set;} // it owned by one attribute 
    public CategoryAttribute{get;set;} // it owned by one category attribute 
} 

我不太確定如何首先在代碼中表示關係或主鍵和外鍵。希望我可以在需要時加強我的回答(如果可以的話)。但希望我的關於每個對象的關係和類設計的插圖。

1

我覺得這樣的事情可能會爲你工作...

public class Category 
{ 
    public int CategoryId { get; set; } 

    public string Name { get; set; } 
    public string Description { get; set; } 

    public virtual ICollection<Item> Items { get; set; } 
    public virtual ICollection<Attribute> Attributes { get; set; } 
} 

public class Item 
{ 
    public int ItemId { get; set; } 

    public string Name { get; set; } 
    public string Description { get; set; } 

    public int CategoryId { get; set; } 
    public Category Category { get; set; } 
    public virtual ICollection<ItemAttribute> ItemAttributes { get; set; } 
} 

public class Attribute 
{ 
    public int AttributeId { get; set; } 

    public string Name { get; set; } 
    public string Description { get; set; } 

    public virtual ICollection<Category> Categories { get; set; } 
    public virtual ICollection<ItemAttribute> ItemAttributes { get; set; } 
} 

public class ItemAttribute 
{ 
    public int ItemId { get; set; } 
    public int AttributeId { get; set; } 

    public Item Item { get; set; } 
    public Attribute Attribute { get; set; } 

    public string Value { get; set; } 
    public int ValueInt{ get; set; } 
    // etc. 
} 

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<ItemAttribute>() 
     .HasKey(x => new { x.ItemId, x.AttributeId }); 
    modelBuilder.Entity<ItemAttribute>() 
     .HasRequired(x => x.Item) 
     .WithMany(x => x.ItemAttributes) 
     .HasForeignKey(x => x.ItemId) 
     .WillCascadeOnDelete(false); 
    modelBuilder.Entity<ItemAttribute>() 
     .HasRequired(x => x.Attribute) 
     .WithMany(x => x.ItemAttributes) 
     .HasForeignKey(x => x.AttributeId) 
     .WillCascadeOnDelete(false); 
    // AttributeCategories is created for you - but you can do the same as^above to customize 
    // just change 'ICollection<Category> Categories' to collection of 'ItemAttribute' 
} 

// use it like e.g. 
var item = new Item { Name = "ItemTest", }; 
var attribute = new Attribute { Name = "attributeTest", }; 
item.ItemAttributes = new List<ItemAttribute> 
{ 
    new ItemAttribute { Item = item, Attribute = attribute, Value = "test", }, 
}; 
var category = new Category 
{ 
    Name = "cat1", 
    Items = new[] 
    { 
     item, 
     new Item{ Name = "Item1", }, 
     new Item{ Name = "Item2", }, 
     new Item{ Name = "Item3", }, 
     new Item{ Name = "Item4", }, 
     new Item{ Name = "Item5", }, 
    }, 
    Attributes = new[] 
    { 
     attribute, 
     new Attribute{ Name = "att1", }, 
     new Attribute{ Name = "att2", }, 
    } 
}; 
db.Categories.Add(category); 
db.SaveChanges(); 
var categories = db.Categories.ToList(); 

ItemAttribute用於連接和存儲values

而且您將需要根據您的要求進一步調整。

+0

謝謝,迄今爲止工作得很好。現在我想不僅有字符串屬性,還有下拉菜單和複選框。我怎麼能延伸到那個? – Sven 2013-04-12 10:15:51

+1

是的,你還有一些工作要做 - 這是爲了讓你指向我希望的正確方向。那裏沒有直接的答案。你可以添加多個字段,就像我提示的那樣 - 在ItemAttribute中有text,int,bool,並根據屬性的'type'使用你需要的任何字段。您也可以嘗試繼承 - 即使ItemAttr成爲基礎並使用幾個attr類型進行擴展 - 但這必然會導致一些問題。可以工作,但(但我沒有時間atm嘗試)。我建議保持簡單 - 爲每個'原始類型'添加多個'可空'字段,你應該沒問題。 – NSGaga 2013-04-12 11:03:50

+1

如果你嘗試繼承 - 那麼我建議將它保留在'TPH'(no [Table()] eg)中 - 因爲它有更多的工作機會(因爲它實際上全部在同一個表中,就像現在一樣)。請檢查我製作的詳細示例(比您需要的更多)。 http://stackoverflow.com/questions/15885279/multiple-inheritance-levels-in-ef-code-firs。自己嘗試一下 - 發佈你的管理 - 我會試着去看看它。 – NSGaga 2013-04-12 11:07:39