我是Entity Framework的新手,这也是我第一次在Stack Overflow上发帖,请跟我一起去。
我正在开发一个由多个对象组成的项目,我希望将其保存到我的数据库中。我正在使用单个上下文和一系列存储库类来访问它们。
当我尝试保存实体时,它似乎保存了与其关联的所有虚拟实体,即使该实体已存在于数据库中也是如此。
这些是我的课程:
public class Requirement
{
public int ID { get; set; }
public DateTime DateDue { get; set; }
public DateTime DateCompleted { get; set; }
public virtual Standard Standard { get; set; }
public virtual Project Project { get; set; }
}
public class Standard
{
public int ID { get; set; }
public int AgencyID { get; set; }
public string Name { get; set; }
public virtual Agency Agency { get; set; }
}
public class Project
{
public int ID { get; set; }
public bool Active { get; set; }
public virtual Agency Agency { get; set; }
public virtual Department Department { get; set; }
}
这是我创建一些数据的方法:
public class RequirementRepository
{
public static string CreateMockData()
{
StandardRepository stdRep = new StandardRepository();
ProjectRepository projRep = new ProjectRepository();
RequirementRepository reqRep = new RequirementRepository();
Project project = projRep.Find(1);
StringBuilder sb = new StringBuilder()
foreach (Standard s in stdRep.FindByAgencyID(project.Agency.ID))
{
Requirement r = new Requirement();
r.Project = project;
r.Standard = s;
r.DateCompleted = (DateTime)SqlDateTime.MaxValue;
r.DateDue = DateTime.Now.AddDays(90);
r = reqRep.Save(r);
sb.AppendLine(String.Format("Saved Requirement ID {0} with Project ID {1}<br>", r.ID, r.Project.ID));
}
return sb.ToString();
}
}
这里是关联的存储库代码:
public class ProjectRepository
{
public Project Find(int id)
{
using (var db = new MyContext())
{
return db.Projects
.Include(p => p.Agency)
.Include(p => p.Department)
.First(p => p.ID.Equals(id));
}
}
}
public class StandardRepository
{
public List<Standard> FindByAgencyID(int agencyID)
{
using (var db = new MyContext())
{
return db.Standards.Where(r => r.AgencyID == agencyID).ToList();
}
}
}
public class RequirementRepository
{
public Requirement Save(Requirement requirement)
{
using (var db = new MyContext())
{
Requirement retVal = requirement;
if (requirement.ID.Equals(0))
{
retVal = db.Requirements.Add(requirement);
}
else
{
db.Entry(requirement).State = EntityState.Modified;
}
db.SaveChanges();
return retVal;
}
}
}
当我运行这个方法时,我希望它能够在数据库中插入一些新的需求,项目ID为1,标准ID为其标准ID。相反,它为它添加的每个需求创建一个全新的项目和一个全新的标准,然后将这些ID分配给需求。
我和我的导师(他也是Entity Framework的新手)非常困惑,我似乎无法在其他地方找到任何相关信息。我希望有人可以帮忙。
提前致谢!
答案 0 :(得分:0)
每个上下文都会跟踪加载,修改的实体和添加的实体。
您的存储库需要看起来像这样......
public class StandardRepository
{
MyContext _context;
public StandardRepository(MyContext context)
{
_context = context;
}
public List<Standard> FindByAgencyID(int agencyID)
{
return _context.Standards.Where(r => r.AgencyID == agencyID).ToList();
}
}
public class RequirementRepository
{
MyContext _context;
public RequirementRepository(MyContext context)
{
_context = context;
}
public Requirement Save(Requirement requirement)
{
Requirement retVal = requirement;
if (requirement.ID.Equals(0))
{
retVal = _context.Requirements.Add(requirement);
}
else
{
_context.Entry(requirement).State = EntityState.Modified;
}
_context.SaveChanges();
return retVal;
}
}
public class RequirementRepository
{
public static string CreateMockData()
{
using(MyContext context = new MyContext())
{
StandardRepository stdRep = new StandardRepository(context);
ProjectRepository projRep = new ProjectRepository(context);
RequirementRepository reqRep = new RequirementRepository(context);
Project project = projRep.Find(1);
StringBuilder sb = new StringBuilder()
foreach (Standard s in stdRep.FindByAgencyID(project.Agency.ID))
{
Requirement r = new Requirement();
r.Project = project;
r.Standard = s;
r.DateCompleted = (DateTime)SqlDateTime.MaxValue;
r.DateDue = DateTime.Now.AddDays(90);
r = reqRep.Save(r);
sb.AppendLine(String.Format("Saved Requirement ID {0} with Project ID {1}<br>", r.ID, r.Project.ID));
}
}
return sb.ToString();
}
}
答案 1 :(得分:0)
根据我的理解,您不必手动设置已修改对象的状态,除非您已从其上下文中分离它。 EF跟踪对象状态。
我喜欢用这样的东西:
public abstract class EntityRepositoryBase<TEntity> : IDisposable, IEntityRepositoryBase<TEntity> where TEntity : class , IEntityWithId
{
protected EntityRepositoryBase()
{
Context = new SomeEntities();
}
public abstract ObjectSet<TEntity> EntityCollection { get; }
public SomeEntities Context { get; set; }
public TEntity GetById(int id)
{
return EntityCollection
.FirstOrDefault(x => x.Id == id);
}
public void Dispose()
{
Context.Dispose();
}
}
然后在派生存储库中:
public class AnswerRepository : EntityRepositoryBase<AnswerEntity>, IAnswerRepository
{
public override ObjectSet<AnswerEntity> EntityCollection
{
get { return Context.AnswerEntities; }
}
}
我使用ninject将存储库注入到相关的类中,但是你应该能够得到类似的:
using (var repo = new AnswerRepository())
{
// modifying via Context
var someEntity = repo.GetById(someId);
someEntity.Value = "1";
repo.Context.SaveChanges();
//modifying via repo
repo.Delete(anotherEntity);
}
然后做你需要做的事。如果需要执行存储库外修改,然后在存储库中执行SaveChanges()以及任何特定的CRUD类型方法,则通过接口IEntityRepositoryBase公开上下文。一旦超出范围,对象和底层连接将被关闭。