2015-11-21 3 views
0

Я работаю над проектом ASP.NET MVC, с кодом C# и EF.Свойства динамического объекта C# ASP.Net MVC

Я должен добавить динамические свойства к объектам. Например:

У меня есть автомобиль в качестве базового объекта. Я могу добавить к нему пользовательские свойства, такие как мощность, длина, цвет и т. Д.

Свойства могут быть логическими, int, string или select (т. Е. Мне нужно создать флажок, ввести или выбрать элементы html, когда пользователь вводит значения для этих свойств).

Свойства должны иметь пользовательские правила проверки (т. Е. Требуемые, только номер, только диапазон и т. Д.).

Можете ли вы, ребята, дать мне какие-либо подсказки или указания, как это сделать?

Спасибо

+0

Я предлагаю вам использовать ViewModel, а затем сопоставить свою сущность. см. это http://www.codeproject.com/Articles/1043977/Mapping-ViewModel-to-Model-in-ASP-NET-MVC-using-Im –

+0

Вам следует отобразить модель EP для просмотра модели; добавить аннотацию данных к свойствам модели представления. – user1672994

+0

Проблема в том, что мне нужно создать динамическую модель из базы данных. Свойства в модели могут быть добавлены динамически, и у них есть все типы данных (int, string, bool, List ). Кроме того, мне нужно сохранить эти свойства в таблице, и это та часть, которую я не знаю, как это сделать. – Tomislav

ответ

1

Если вы действительно имеете динамические свойства, которые вы не сможете сделать это (непосредственно) с EF6 поскольку EF6 предполагает базу данных соотношения. и реляционная база данных должна знать, какие столбцы следует ожидать.

Теперь у вас есть 2 варианта.

Option1: использовать не реляционную базу данных с EF 7. Вы можете посмотреть здесь https://msdn.microsoft.com/en-us/magazine/dn890367.aspx еще несколько деталей о EF7, но в основном в не базе данных отношений можно хранить любой JSon блоб - так и динамические свойства

Вариант 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. (И если вы хотите хранить строки, ints и т. Д., Вы можете создавать разные типы KeyValuePair, по одному для каждого типа хранилища)

Будьте осторожны с производительностью, хотя, если вы используете динамические свойства, подобные этому.

Update:

Если вы хотите проверить динамический объект, как это вы хотите реализовать 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; 
    } 
} 
+0

Я никогда не работал с EF7, как я могу добавлять свойства другого типа (т. Е. Int, string, boolean, select items) и проверять их с помощью DataAnnotations? Возможно ли это сделать через какой-то полиморфизм? – Tomislav

+0

Я не думаю, что вы можете проверить свойства через dataannotations напрямую с помощью динамических свойств. Я добавил файл IValidableObject, который вы можете использовать для проверки вашего объекта. – Batavia

+0

также да, вы получили бы KeyStringValie, KeyIntValue и т. Д. Все наследования от BaseKeyValue. и полиморфизм применяется там – Batavia

0

Вы можете создавать и использовать таблицы в БД динамически , хотя это не так просто.

Во-первых, вам нужно будет хранить метаданные о своих таблицах - каковы их имена, каковы их свойства, каковы типы этих свойств и т. Д.

Во-вторых, вам нужно создать объекты для доступа к этим таблицам, а также, 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(); 
    } 
} 

Вы можете создавать DLL динамически, без промежуточного кода С # с помощью System.Reflection.Emit. Или вы можете сгенерировать код 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(); 
+0

Будет ли это применимо к моей проблеме: http://stackoverflow.com/questions/11486286/asp-net-mvc-3-editor-for-dynamic-property – Tomislav

+0

@ Томислав, проблема с бритвами, я думаю, может быть решена с помощью кода if if (model.GetType() == typeof (int)) ... else if (model.GetType() == typeof (bool)) ... и т. д. –

Смежные вопросы