我正在开展ASP.NET MVC
项目,首先使用C#
和EF
代码。
我需要向实体添加动态属性。例如 -
我有一辆汽车作为基础物体。我可以为它添加自定义属性,如引擎功率,长度,颜色等。
属性可以是boolean,int,string或select options(即,当用户输入这些属性的值时,我必须创建复选框,输入或选择html元素。)
属性必须具有自定义验证规则(即必需,仅限数字,范围等)。
你们能给我任何线索或指导如何实现这个目标吗?
谢谢
答案 0 :(得分:1)
如果您确实拥有动态属性,则无法使用EF6(直接)执行此操作,因为EF6假定为关系数据库。并且关系数据库需要知道期望哪些列。
现在你有两个选择。
选项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;
}
}
答案 1 :(得分:0)
您可以动态地在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
的帮助下,您可以在没有中间C#代码的情况下动态生成DLL。或者您可以生成C#代码并使用System.CodeDom.Compiler
进行编译(这种方式更简单)。您也可以尝试使用Roslyn编译器(但我没有足够的经验来建议)。
第三,您需要加载已编译的DLL并使用DbContext
创建modelBuilder.Configurations.AddFromAssembly(...)
。
您可以在程序集中找到所需类型并使用它来访问数据:
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();