反映与儿童一起更新源实体与儿童的目标

时间:2012-12-05 16:16:27

标签: c# entity-framework reflection code-first

对于所有反思专家,我需要一些帮助。我正在研究一种通用方法,以便能够使用CodeFirst和EF5在MVC应用程序中使用分层数据分配。用户将更改应用于父对象(源),此方法将填充子对象(目标)。它没有像我期望的那样工作。任何指针都将非常感激。

以下方法“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);
        }
    }
}

问题是:它似乎没有正确遍历子对象,也没有按照我的预期更新目标。寻找输入和建议,因为我不像我想的那样精通反思。

更新时间:12/06/2012

好的,所以我相信我已经找到了问题但仍在寻找解决方案。这个问题来自我团队中的另一个开发人员,假设对象模型是合理的。但是,我们当前正在测试的实体似乎没有从db中检索种子值。

在定义此关联的OnModelCreating()方法中没有定义任何内容,尽管从实体模型正确创建了表,并且正在从dbSeed()方法正确加载数据。我可以从db运行select语句并获取正确的数据。似乎实体模型外键关联可能无效,从而阻止了正确的数据检索。任何帮助将不胜感激。

更新:好的,最后检索正确的数据。这终于做到了。

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

2 个答案:

答案 0 :(得分:1)

我不确定我是否理解这个问题,但您似乎只需要确保sourceMemberAssociation(或后代)或{{1 }}

你可以快速而肮脏的方式将结果值转换为Association,并检查转换是否成功,如下所示:

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); } } 个对象。

答案 1 :(得分:0)

请参阅原始帖子“更新”以获得解决方案。