0

ランタイムから動的に EntityTypeConfiguration を生成することを考えていましたが、モデルで EF 依存関係を望んでいません [そのため、データ注釈を避けます]。

だから私はカスタム属性を宣言します(または後で任意の構成ファイルにすることができます)

[AttributeUsage(AttributeTargets.Property, AllowMultiple=true )]
public class PersistableMemberAttribute : Attribute
{
    public bool Iskey;
    public bool IsRequired;
    public bool IsIgnored;
    public bool IsMany;
    public string HasForeignKey;
    public bool PropertyIsRequired;
    public bool PropertyIsOptional;
}

そして、ここに私のモデルの1つが次のように見えます:

 public class Blog
{
    [PersistableMember(Iskey=true)]
    public Guid BlogId { get; set; }

    [PersistableMember(PropertyIsRequired = true)]
    public string Name { get; set; }

    public string Url { get; set; }

    [PersistableMember(IsIgnored=true)]        
    public int Rating { get; set; }

    [PersistableMember(IsMany =true)]
    public ICollection<Post> Posts { get; set; }
}

ここで、属性値に基づいて実行時に構成を動的に作成する汎用 EntityTypeConfiguration を作成します。

 public class GenericEntityConfiguration<T> : EntityTypeConfiguration<T> where T : class
{
    public GenericEntityConfiguration()
    {
        var members = typeof(T).GetProperties();
        if (null != members)
        {
            foreach (var property in members)
            {
                var attrb= property.GetCustomAttributes(typeof( PersistableMemberAttribute ),false).OfType<PersistableMemberAttribute>();
                if (attrb != null && attrb.Count() > 0)
                {
                    foreach (var memberAttributute in attrb)
                    {
                        if (memberAttributute.Iskey || memberAttributute.IsIgnored)
                        {
                            var entityMethod = this.GetType().GetMethod("Setkey");
                            entityMethod.MakeGenericMethod(property.PropertyType)
                              .Invoke(this, new object[] { property, memberAttributute });
                        }

                        if (memberAttributute.IsRequired)
                        {
                            var entityMethod = this.GetType().GetMethod("SetRequired");
                            entityMethod.MakeGenericMethod(property.PropertyType)
                              .Invoke(this, new object[] { property, memberAttributute });
                        }

                        if (memberAttributute.PropertyIsRequired || memberAttributute.PropertyIsOptional)
                        {
                            var entityMethod = this.GetType().GetMethod("SetPropertyConfiguration");
                            entityMethod.MakeGenericMethod(property.PropertyType)
                              .Invoke(this, new object[] { property, memberAttributute });
                        }
                    }
                }
            }
        }

    }

    public void SetPropertyConfiguration<TResult>(PropertyInfo propertyInfo, PersistableMemberAttribute attribute)
    {
        var functorParam = Expression.Parameter(typeof(T));
        var lambda = Expression.Lambda(
            Expression.Property(functorParam, propertyInfo)
        , functorParam);

        if (attribute.PropertyIsRequired)
        {
            this.Property<TResult>((Expression<Func<T, TResult>>)lambda).IsRequired();
        }
        if (attribute.PropertyIsOptional)
        {
            this.Property<TResult>((Expression<Func<T, TResult>>)lambda).IsOptional();

        }
    }

    public void Setkey<TResult>(PropertyInfo propertyInfo, PersistableMemberAttribute attribute)
    {
        var functorParam = Expression.Parameter(typeof(T));
        var lambda = Expression.Lambda(
            Expression.Property(functorParam, propertyInfo)
        , functorParam);

        if (attribute.Iskey)
        {
            this.HasKey<TResult>((Expression<Func<T,TResult>>)lambda);
        }
        if (attribute.IsIgnored)
        {
            this.Ignore<TResult>((Expression<Func<T, TResult>>)lambda);
        }
    }

    public void SetRequired<TResult>(PropertyInfo propertyInfo, PersistableMemberAttribute attribute) where TResult : class
    {
        var functorParam = Expression.Parameter(typeof(T));
        var lambda = Expression.Lambda(
            Expression.Property(functorParam, propertyInfo)
        , functorParam);
        if (attribute.IsRequired)
        {
            this.HasRequired<TResult>((Expression<Func<T, TResult>>)lambda);
        }
    }

}

しかし、コンパイルエラーが発生しました

エラー 1 型 'TResult' は、ジェネリック型またはメソッド 'System.Data.Entity.ModelConfiguration.Configuration.StructuralTypeConfiguration.Property(System.Linq. Expressions.Expression>)' D:\R&D\UpdateStorePOC\UpdateStorePOC\Data\GenericEntityConfiguration.cs 63 17 UpdateStorePOC

これら2つのステートメントについて:

        this.Property<TResult>((Expression<Func<T, TResult>>)lambda).IsRequired();

        this.Property<TResult>((Expression<Func<T, TResult>>)lambda).IsOptional();

つまり、メソッドを値型に制限するには、メソッドに制約を設定する必要があります。C# では、これは 'struct' キーワードで行われます。

public void SetPropertyConfiguration<TResult>(PropertyInfo propertyInfo, PersistableMemberAttribute attribute) Where TResult : struct

しかし、私のプロパティタイプは文字列やint、bool doubleなどのクラスになる可能性があるため、解決策ではありません。したがって、それらをこのメソッドに送信できるかどうかはまったく明確ではありません。他に方法がないかどうか、この問題を解決するのを手伝ってください。

4

1 に答える 1

0

モデルに EF 依存関係は必要ありません。

流暢なマッピングを使用すると、ほぼ到達し、それ以上近づくことはありません。属性は、構成ファイルに移動することを意図していても、モデルを EF フットプリントから解放することはできません。1さらに悪いことに、モデルと EF のマッピングの間に 2 番目のマッピング レイヤーを (必要に応じて) 追加するだけです。私は欠点しか見ません:

  • モデルのメタデータを維持する必要があります。おそらく、通常の流暢なマッピングに劣らず、(おそらく) コンパイル時のチェックを行わずに手動で編集された厄介な XML で維持する必要があります。
  • EF のマッピングがカバーしているが、まだあなたのマッピングがカバーしていないケースをカバーするために、コードを拡張し続けます。2したがって、これはエネルギーの無駄です。最終的には、基本的に EF のマッピング メソッドを書き直すことになります。
  • EF をアップグレードするときは、指を交差させておく必要があります。
  • バグや問題が発生した場合、コミュニティからサポートを受けるのは困難です。

あなたの質問に対する私の答えは、この問題を解決するのに役立ちます: すぐに流暢なマッピングを使用してください。複雑にしないでおく。


1たとえば、virtual遅延読み込み用のプロキシを有効にするには、引き続き修飾子を使用する必要があります。

2継承、マップされていない外部キー、最大長、db データ型などのサポートと同様に、これはしばらく続く可能性があります。

于 2012-11-18T01:14:08.323 に答える