0

私はASP.NET MVCプロジェクトに取り組んでC#おり、EFコードを最初に使用しています。

エンティティに動的プロパティを追加する必要があります。例えば ​​-

ベースオブジェクトとして車を持っています。エンジン出力、長さ、色などのカスタム プロパティを追加できます。

プロパティは、ブール値、int、文字列、または選択オプションにすることができます (つまり、ユーザーがこれらのプロパティの値を入力するときに、チェックボックスを作成し、html 要素を入力または選択する必要があります)。

プロパティには、カスタム検証規則 (つまり、必須、数値のみ、範囲のみなど) が必要です。

これを達成するための手がかりや指示を教えてもらえますか?

ありがとうございました

4

2 に答える 2

2

本当に動的プロパティがある場合、EF6 はリレーション データベースを想定しているため、EF6 でこれを (直接) 行うことはできません。また、リレーショナル データベースは、期待される列を認識する必要があります。

これで 2 つのオプションが得られました。

オプション 1: EF 7 で非リレーショナル データベースを使用します。EF7 の詳細については、https: //msdn.microsoft.com/en-us/magazine/dn890367.aspx をご覧ください。任意の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;}

}

これで、車はこの baseobject から継承できます。KeyValuePair オブジェクトを作成するには、まだ作業を行う必要があります。(そして、文字列、int などを保存したい場合は、ストレージ タイプごとに 1 つずつ、異なる 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;
    }
 }
于 2015-11-21T19:08:37.957 に答える
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();
    }
}

の助けを借りて、中間 C# コードなしで DLL を動的に生成できますSystem.Reflection.Emit。または、C# コードを生成し、それを使用System.CodeDom.Compilerしてコンパイルすることもできます (この方法の方が簡単です)。また、Roslyn コンパイラを試すこともできます (ただし、アドバイスできるほど十分な経験がありません)。

3 番目に、コンパイル済みの DLL をロードしDbContextmodelBuilder.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();
于 2015-11-21T19:34:59.143 に答える