我有一個三層應用程序。這些圖層是DAL,BL和UI。我使用automapper將從數據庫上下文中取得的實體轉換爲上層圖層。據我所知,被映射的實體不能被EF跟蹤。如何使用實體框架使用DTO更新數據庫中的實體
無論如何,我面臨的問題發生在更新DB中存在的實體時,更確切地說是由DTO實體更新EF實體。來自上層的DTO被映射回實體以完成更新操作。但是,從DTO實體映射而來,其所有導航屬性和集合都不存在於上下文中,因爲它們未被跟蹤。
EF接受此實體及其實體圖形作爲新信息,而不考慮該實體及其中包含的某些實體可能已經存在於上下文中的事實。
這裏舉一些例子。
我有兩個型號,Student
和Standard
。
public class Student
{
[Key]
public Guid StudentID { get; set; }
public string StudentName { get; set; }
public DateTime DateOfBirth { get; set; }
public decimal Height { get; set; }
public float Weight { get; set; }
public Standard Standard { get; set; }
}
public class Standard
{
[Key]
public Guid StandardId { get; set; }
public string StandardName { get; set; }
public ICollection<Student> Students { get; set; }
}
我的背景:
public class SchoolContext : DbContext
{
public DbSet<Student> Students { get; set; }
public DbSet<Standard> Standards { get; set;}
}
我也有一個StudentMap
和StandardMap
看起來一樣上面提到的車型。
Automapper簡介:
public class AutomapperProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<Student, StudentMap>();
Mapper.CreateMap<StudentMap, Student>();
Mapper.CreateMap<Standard, StandardMap>();
Mapper.CreateMap<StandardMap, Standard>();
}
}
在這裏,我運行代碼:
Mapper.AddProfile(new AutomapperProfile());
var student1 = new Student
{
DateOfBirth = DateTime.Now,
Height = 195,
StudentID = Guid.NewGuid(),
StudentName = "Bob",
Weight = 144
};
var student2 = new Student
{
DateOfBirth = DateTime.UtcNow,
Height = 170,
StudentID = Guid.NewGuid(),
StudentName = "John",
Weight = 95,
};
var standard = new Standard
{
StandardId = Guid.NewGuid(),
StandardName = "New Standard",
Students = new List<Student> { student1 }
};
using (var schoolContext = new SchoolContext())
{
schoolContext.Standards.Add(standard);
schoolContext.Students.Add(student2);
schoolContext.SaveChanges();
var standardInContext = schoolContext.Standards.First();
var studentInContext = schoolContext.Students.First(student => student.StudentID == student2.StudentID);
var mappedStandad = Mapper.Map<Standard, StandardMap>(standardInContext);
var mappedStudent = Mapper.Map<Student, StudentMap>(studentInContext);
mappedStandad.Students.Add(mappedStudent);
var standardEf = Mapper.Map<StandardMap, Standard>(mappedStandad);
//On attach attempt exception will be thrown
//because standard with the same Id already exist in context
schoolContext.Set<Standard>().Attach(standardEf);
schoolContext.Entry(standardEf).State = EntityState.Modified;
// with this solution two additional student will be added to the context,
// exception will be thrown on SaveChanges, because students with
// same ID already exist
// var standardEf = Mapper.Map(mappedStandad, standardInContext);
// schoolContext.Set<Standard>().Attach(standardEf);
// schoolContext.Entry(standardEf).State = EntityState.Modified;
schoolContext.SaveChanges();
}
我會感謝您的幫助!我已經檢查了我所能做的,但是徒勞無功。
很好,你的情況發生在一個問題用Mapper.Map
謝謝,看起來像我的問題的解決方案。但是當我的實體包含很多對其他對象的引用時,它就變成了常規 –