1

リフレクションの専門家の皆さん、私は助けが必要です。私は、CodeFirstとEF5を使用するMVCアプリケーションで階層データ割り当てを使用できるようにするためのgnericメソッドに取り組んでいます。ユーザーは親オブジェクト(ソース)に変更を適用し、このメソッドは子オブジェクト(ターゲット)にデータを入力します。期待どおりに動作していません。任意のポインタをいただければ幸いです。

以下のメソッド「CopyEntity」は、子エンティティを持つソースエンティティを取得し、同じタイプと構造のターゲットエンティティを更新することを目的としています。基本タイプの「関連付け」を継承し、メンバーに「NoInherit」属性を持たないエンティティのみを更新することを検討しています。すべてのプロパティが「関連付け」から更新されるわけではありません

public class ClassCode : Inheritable<ClassCode>
{

    // Base Properties ----------------------------------
    public int LobId { get; set; }
    public virtual LOB LOB { get; set; }
    public bool IsVirtual { get; set; }
    //public string Name { get; set; }
    public string Description { get; set; }

    [Required(ErrorMessage = "Select Code")]
    public string Code { get; set; }
    //enable to force recreation of the database
    public string IID { get; set; }

    public virtual ICollection<ClassSubjectivityAssoc> Subjectivities{ get; set; }
}

public class ClassSubjectivityAssoc : Association
{
    [Column("SubjectivityId")]
    public override int AssociationId { get; set; }

    [ForeignKey("AssociationId")]
    public virtual Subjectivity Subjectivity { get; set; }

    public int ClassCodeId { get; set; }
    [ForeignKey("ClassCodeId")]
    public virtual ClassCode ClassCode { get; set; }
}

public abstract class Association  : BaseEntity
{
    public DateTime Start { get; set; }
    public DateTime? End { get; set; }
    public bool IsCurrent { get; set; }
    public int Order { get; set; }
    public bool BreakInheritance { get; set; }
    public int? InhId { get; set; }
    public virtual ClassCode InhClass { get; set; }
    public int CodeId { get; set; }
    [ForeignKey("ClassCodeId")]
    public virtual Code ClassCode { get; set; }
    public abstract int AssociationId {get; set;}
}

public class BaseEntity
{
    private static DateTime CREATE_DATE
    {
        get { return DateTime.Now; }
    }

    [NoInherit]
    public int Id { get; set; }

    [NoInherit]
    public string CreatedBy { get; set; }
    [NoInherit]
    public DateTime Created { get; set; }

    [NoInherit]
    public string LastModifiedBy { get; set; }
    [NoInherit]
    public DateTime LastModified { get; set; }

    public bool IsActive { get; set; }
}

protected void CopyEntity(Inheritable<T> source, Inheritable<T> target)
{
    Type sourceType = source.GetType();
    Type targetType = target.GetType();
    // ensure that the types can be assigned to one another
    //if (!targetType.IsAssignableFrom(sourceType)) return;

    // loop through the properties of the source system
    foreach (PropertyInfo sourceMember in sourceType.GetProperties().Where(sourceMember => sourceMember.GetCustomAttribute(typeof(NoInheritAttribute)) == null))
    {
        var targetMember = targetType.GetProperty(sourceMember.Name);
        // if the property doesn't exist in the target, let's get out
        if (targetMember == null) continue;

        // check if this property is a Collection
        bool isCollection = (sourceMember.PropertyType.IsGenericType && sourceMember.PropertyType.GetInterfaces().Any(x =>
                                      x.IsGenericType &&
                                      x.GetGenericTypeDefinition() == typeof(IEnumerable<>)));

        // if we are not dealing with associations, let's get outta herre
        if (!(isCollection
                  ? sourceMember.PropertyType.GetGenericArguments().Single()
                  : sourceMember.PropertyType)
                 .IsSubclassOf(typeof(Association))) continue;

        if (isCollection)
        {
            IEnumerable<Association> targetCollection = (IEnumerable<Association>) targetMember.GetValue(target);
            // Loop through the collection and evaluate
            foreach (Association sourceAssociation in (IEnumerable) sourceMember.GetValue(source))
            {
                Association targetAssociation =
                    targetCollection.SingleOrDefault(t => t.AssociationId == sourceAssociation.AssociationId);
                CopyAssociation(sourceAssociation, targetAssociation);
            }
        }
        else
        {
            Association sourceAssociation = (Association) sourceMember.GetValue(source);
            Association targetAssociation = (Association) targetMember.GetValue(target);
            CopyAssociation(sourceAssociation, targetAssociation);
        }
    }
}

問題は次のとおりです。子オブジェクトを適切にトラバースしていないようで、予想どおりにターゲットを更新しません。私はリフレクションに精通していないので、意見や提案を探しています。

更新:2012年12月6日

わかりました。問題は見つかったと思いますが、それでも解決策を探しています。この問題は、オブジェクトモデルが適切であるという前提で、私のチームの別の開発者から発生しました。ただし、現在テストしているエンティティは、シードされた値をデータベースから取得していないようです。

テーブルはエンティティモデルから適切に作成され、データはdbSeed()メソッドから適切にロードされていますが、この関連付けを定義するOnModelCreating()メソッドには何も定義されていません。データベースからselectステートメントを実行して、適切なデータを取得できます。エンティティモデルの外部キーの関連付けが無効であるため、正しいデータの取得が妨げられている可能性があります。どんな助けでも大歓迎です。

更新:わかりました、最終的に正しいデータを取得します。これはついにそれをしました。

    modelBuilder.Entity<ClassSubjectivityAssoc>()
                .HasRequired(c => c.ClassCode)
                .WithMany(u => u.Subjectivities)
                .HasForeignKey(f => f.ClassCodeId);
4

2 に答える 2

1

質問を理解しているかどうかはわかりませんが、それが(または子孫)またはのコレクションのsourceMemberいずれかであることを確認する必要があるようです。AssociationAssociation

結果の値をAssociationにキャストし、キャストが成功したかどうかを確認することで、これをすばやく汚い方法で行うことができます。たとえば、単純なプロパティの場合は次のようになります。

Association sourceAssociation = sourceMember.GetValue(source) as Association;
if (sourceAssociation != null) // the source is a valid Association
{
   Association targetAssociation = targetMember.GetValue(target) as Association;
   if (targetAssociation != null) // the destionation too
   {
        CopyAssociation(sourceAssociation, targetAssociation);
   }
}

コレクションにも同様のコードがあります


Association示したメソッドはオブジェクトツリーを下降しないため、エンティティに直接接続されているオブジェクトでのみ機能します。

于 2012-12-05T16:29:03.683 に答える
0

解決策については、元の投稿「UPDATES」を参照してください。

于 2012-12-06T16:06:46.043 に答える