子对象也被保存

时间:2014-01-27 05:50:43

标签: entity-framework c#-4.0 entity-framework-4.1

我正在使用实体框架创建一对一的关系。我创建了两个类Student和IssueMaster。这两个类都派生自基本实体类

public class Entity
{
    public Entity()
    {
        CreatedOn = DateTime.Now;
    }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }

    public DateTime CreatedOn { get; set; }
}

public class Student : Entity
{
    public string Name { get; set; }
    public string MobileNo { get; set; }
    public string Address { get; set; }
}

public class IssueMaster : Entity
{
    public IssueMaster()
    {
        IssueDate = DateTime.Now;
    }

    public virtual Student Student { get; set; }
    public DateTime IssueDate { get; set; }
    public DateTime? ReturnDate { get; set; }
}

和Student和IssueMaster类的映射是,

public class StudentMap : EntityTypeConfiguration<Student>
{
    public StudentMap()
    {
        ToTable("Student");

        Property(x => x.Name)
            .IsRequired()
            .HasMaxLength(20);

        Property(x => x.MobileNo)
            .IsRequired()
            .HasMaxLength(10)
            .IsFixedLength();

       Property(x=>x.Address).HasMaxlength(50);
    }
}

public class IssueMasterMap : EntityTypeConfiguration<IssueMaster>
{
    public IssueMasterMap()
    {
        ToTable("IssueMaster");

        Property(x => x.IssueDate).IsRequired();
        Property(x => x.ReturnDate).IsOptional();
        HasRequired(x => x.Student);
    }
}

保存实体的保存方法是

    public static bool Save<T>(T entity) where T : Entity
    {
        var context = SessionManager.GetCurrentContext;
        context.Entry(entity).State = EntityState.Added;
        return context.SaveChanges() > 0;
    }

问题是当我们将IssueMaster对象保存在数据库中时,附加到该IssueMaster对象的Student对象也会保存在数据库中。

在代码中做什么,以便当我们从附加到该IssueMaster对象的数据库中保存IssueMaster对象和Student对象时,只保存IssueMaster对象? (像Nhibernate中的SaveOrUpdate方法一样)

1 个答案:

答案 0 :(得分:1)

您的问题是将条目状态设置为已添加 - 将整个对象图更改为已添加状态(即包括所有引用的实体)。如果您将使用Student属性而不是在已保存实体中使用StudentId对象,则可以避免添加新的Student条目。或者,如果您将手动将学生的实体状态设置为 Unchanged Modified

第一个选项是使您的Save方法非通用。这将允许您直接设置导航属性状态:

 context.Entry(issueMaster.Student).State = EntityState.Unchanged;

但是如果你想拥有泛型方法,你唯一的选择就是反射(这是性能命中)。因此,所有实体都从基类Entity类型继承,您可以获取从Entity类型继承的属性并检查其ID。如果它具有Guid.Empty值,则对象是新的并且未保存在数据库中,否则您应该设置适当的实体状态:

public static bool SaveOnlyAddedEntities<T>(T entity) where T : Entity
{
    var context = new ZorgContext();
    context.Entry(entity).State = EntityState.Added;
    var entry = context.Entry(entity);

    Type type = typeof(T);
    var flags = BindingFlags.Instance | BindingFlags.Public;

    var unchangedDependencies =
        type.GetProperties(flags)
            .Where(p => p.PropertyType.IsSubclassOf(typeof(Entity)))
            .Select(p => (Entity)p.GetValue(entity))
            .Where(e => e.Id != Guid.Empty);

    foreach (var dependency in unchangedDependencies)
        context.Entry(dependency).State = EntityState.Unchanged;

    return context.SaveChanges() > 0;
}

注意:此方法显示使用非集合属性。