![](/img/trans.png)
[英]How to Create Model with Properties of Related Object in C# ASP.NET MVC?
[英]C# ASP.Net MVC dynamic object properties
我正在使用C#
和EF
代碼進行ASP.NET MVC
項目。
我需要向實體添加動態屬性。 例如 -
我以汽車為基礎。 我可以為其添加自定義屬性,例如引擎功率,長度,顏色等。
屬性可以是布爾值,整數,字符串或選擇選項(即,當用戶輸入這些屬性的值時,我必須創建復選框,輸入或選擇html元素)。
屬性必須具有自定義驗證規則(即,必填,僅數字,僅范圍等)。
你們能給我任何線索或指導來實現這一目標嗎?
謝謝
如果您確實具有動態屬性,則由於EF6假定有關系數據庫,因此您將無法(直接)使用EF6進行此操作。 關系數據庫需要知道期望哪些列。
現在,您有2個選擇。
選項1:將非關系數據庫與EF 7結合使用。您可以在https://msdn.microsoft.com/en-us/magazine/dn890367.aspx上找到有關EF7的更多詳細信息,但基本上在非關系數據庫中,您可以存儲任何json blob-動態屬性也存儲
選項2:在對象中使用鍵值對。 並存儲這些屬性
class KeyValuePair {
int Id {get; set;}
string name {get; set;}
string stringValue {get; set;}
}
class BaseObject {
int Id {get; set;}
list<KeyValuePair> dynamicProperties {get; set;}
}
現在,您的汽車可以從該基礎對象繼承。 您仍然需要完成創建KeyValuePair對象的工作。 (如果要存儲字符串,整數等,則可以設置不同的KeyValuePair類型,每種存儲類型都可以使用一種)
但是,如果您使用這樣的動態屬性,請小心性能。
更新:
如果要驗證這樣的動態對象,則要實現IValidatableObject
所以你得到
class Car: BaseObject, IValidatableObject {
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
/* code to validate your properties here, for example you need at least 1 engine, 4 wheels etc */
yield return ValidationResult.Success;
}
}
您可以在DB中動態創建和使用表,盡管並非如此簡單。
首先,您需要存儲有關表的元數據-它們的名稱是什么,它們具有的屬性是什么,這些屬性的類型是什么,等等。
其次,您將需要生成實體來訪問這些表以及EntityTypeConfiguration
類,如下所示:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
public class FooTypeConfiguration : EntityTypeConfiguration<Foo>
{
public FooTypeConfiguration()
{
ToTable("Foos");
HasKey(t => t.Id);
Property(t => t.Name).HasMaxLength(200)
.IsRequired();
}
}
您可以借助System.Reflection.Emit
動態生成DLL,而無需中間的C#代碼。 或者,您可以生成C#代碼並使用System.CodeDom.Compiler
進行編譯(這種方式更簡單)。 您也可以嘗試使用Roslyn編譯器(但是我沒有足夠的經驗來推薦它)。
第三,您需要使用modelBuilder.Configurations.AddFromAssembly(...)
加載已編譯的DLL並創建DbContext
。
您可以在程序集中找到所需的類型並使用它來訪問數據:
string typeName = ...;
var type = dynamicLoadedAssembly.GetType(typeName);
var set = dbContext.Set(type); // non-generic DB Set
您可以使用System.Reflection
或dynamic
類型來處理這些對象。 最后,如果要生成C#代碼,則可以生成屬性和某些接口的實現,以按名稱訪問這些屬性:
public interface IAccessorByName : IReadOnlyDictionary<string, object>
{
object this[string name] { get; set; }
}
public Foo : IAccessorByName
{
private static readonly IDictionary<string, Func<Foo, object>> getters = new Dictionary<string, Func<Foo, object>>
{
{ "Id", (foo) => foo.Id },
{ "Name", (foo) => foo.Name },
};
private static readonly IDictionary<string, Action<Foo, object>> setters = new Dictionary<string, Action<Foo, object>>
{
{ "Id", (foo, value) => { foo.Id = (int)value; } },
{ "Name", (foo, value) => { foo.Name = (string)value; } },
};
public int Id { get; set; }
public string Name { get; set; }
public object this[string name]
{
get { return getters[name](this); }
set { setters[name](this, value); }
}
}
使用類似的界面,您可以動態創建,讀取,更新和刪除對象:
string typeName = "Foo";
var fooType = dynamicLoadedAssembly.GetType(typeName);
var foo = (IAccessorByName)Activator.CreateInstance(fooType);
foo["Id"] = 1;
foo["Name"] = "Jon Skeet";
var fooSet = dbContext.Set(fooType);
fooSet.Add(foo);
dbContext.SaveChanges();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.