0

EF がジェネリック エンティティ型をサポートすることになっていないことはわかっていますが、プロジェクトで非常に必要としています... 0 から 5 の複雑なジェネリック プロパティを含む約 200 のクラスがあります。

public class MyCommonProperty
{
    public virtual string Key { get; set; }
}

public class MyCustomClass<T> : MyCommonProperty where T : struct, IComparable, IFormattable, IConvertible
{
    public virtual T Value { get; set; }
    public virtual string DisplayValue { get; set; }

    public MyCustomClass(string key)
    {
        Key = key;
    }
}

public class ConcreteClass
{
    public int Id { get; set; }
    public MyCustomClass<CustomType1> CustomType1 { get; set; }
    public MyCustomClass<CustomType2> CustomType2 { get; set; }
}

これらの POCO を使用して、Entity Framework を使用して DB にキープロパティを保持したいだけです。ここに私のモデルがあります:

  • エンティティ タイプ
    • 具体的なクラス
      • Id ( int、ID)
      • CustomType1 ( MyCommonProperty )
      • CustomType2 ( MyCommonProperty )
  • 複合型
    • MyCommonProperty
      • キー (文字列)

最後に、私の UI では、コードは次のようになります。

using (var db = new ModelContainer())
{
    db.ConcreteClassSet.AddObject(new ConcreteClass()
    {
        CustomType1 = new MyCustomClass<CustomType1>() { Key = "RandomKey1" },
        CustomType2 = new MyCustomClass<CustomType2>() { Key = "RandomKey2" }
    });
    db.SaveChanges();
}

このコードを実行すると、次のエラーが発生します。

ID 'Domain.MyCustomClass`1[[Domain.CustomType1, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' を持つメンバーは、メタデータ コレクションに存在しません。

MyCustomClass は私のedmxで定義されていませんでしたが、 MyCustomClass はメタデータで定義されている MyCommonPropertyでもあるため、EF はこのクラスを気にしません...

コンテナのValidateEntityをオーバーライドしました:

public partial class ModelContainer : DbContext
{
    public ModelContainer()
        : base("name=ModelContainer")
    {
    }

    protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
    {
        if (entityEntry.Entity is ConcreteClass)
            return new DbEntityValidationResult(entityEntry, new List<DbValidationError>());
        return base.ValidateEntity(entityEntry, items);
    }

    public DbSet<ConcreteClass> ConcreteClassSet { get; set; }
}

基本的に、 ConcreteClassの検証をオフにして、常に有効であることを EF に伝えました。この回避策では、db.Save()が機能します。データベースに新しい行が追加され、生成された Id と "RandomKey1" および "RandomKey2" がCustomType1フィールドとCustomType2フィールドに含まれます。

問題は検証です。これらのジェネリック プロパティを含むすべてのエンティティの検証をオフにしたくありませんそこに宣言されている唯一の型がMyCommonPropertyであるため、見つかりません

メタデータを変更して偽の型を追加することで可能になると思います。たとえば、MyCommonPropertyを見つけてコピーし、コピーの名前を'Domain.MyCustomClass`1[[Domain.CustomType1, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' に変更します。

var metadata = (this as IObjectContextAdapter).ObjectContext.MetadataWorkspace;
var metaType = metadata.GetType("MyCommonProperty", "Domain", DataSpace.CSpace);
metaType.Name = "'Domain.MyCustomClass`1[[Domain.CustomType1, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'";
metadata.RegisterItemCollection(metaType);

作り方が思いつかなかったので(知識不足で)、どなたかアイデアやヒントをいただければ幸いです。

4

0 に答える 0