我正在使用实体框架创建一对一的关系。我创建了两个类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方法一样)
答案 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;
}
注意:此方法显示使用非集合属性。