【问题标题】:Child object is also getting saved子对象也被保存
【发布时间】:2014-01-27 05:50:43
【问题描述】:

我正在使用实体框架创建一对一的关系。我创建了两个类 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 方法一样)

【问题讨论】:

  • 你想保存数据库中不存在的全新IssueMaster对象,但你希望它在student_id列中有null吗?
  • 是的,我想在 Student_id 列中使用现有学生 ID 值保存新的 IssueMaster 对象,数据库中已经存在学生记录。

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


【解决方案1】:

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

第一个选项是使您的 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;
}

注意:这种方法展示了使用非集合属性。

【讨论】:

  • 它有效,谢谢,你能分享任何描述与实体框架代码关系的链接吗?
  • @Mahendra 我推荐你看 Julie Lerman EF 系列的复数视角(尤其是Entity Framework in the Enterprise)你也可以搜索她的文章,我相信他们也会包含对 EntityState 变化的解释
猜你喜欢
  • 2015-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-27
  • 2013-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多