反射用子对象更新源实体用子对象作为目标



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

以下方法"CopyEntity"旨在获取具有子实体的源实体,并更新相同类型和结构的目标实体。我们只希望更新那些继承基类型"Association"并且成员上没有"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

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

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

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

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

我真的不确定我是否理解这个问题,但似乎你只需要确保sourceMemberAssociation(或子代)或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);
}
}

以及的类似代码


您显示的方法不会下降到对象树,因此它只适用于直接附加到实体的Association对象。

有关解决方案,请参阅原始文章"更新"。

最新更新