[英]Entity Framework - Update entities without Id
我在互联网上的SO和文章上发现了很多问题,但没有一个能真正解决我的问题。
每天左右,“播放”都会更新(通过包含该信息的XML文件)。
internal Play ParsePlayInfo(XDocument doc)
{
Play play = (from p in doc.Descendants("Play")
select new Play
{
Theatre = new Theatre()
{
//Properties
},
//Properties
LastUpdate = DateTime.Now
}).SingleOrDefault();
var actors = (from a in doc.XPathSelectElement(".//Play//Actors").Nodes()
select new Lecturer()
{
//Properties
});
var parts = (from p in doc.XPathSelectElement(".//Play//Parts").Nodes()
select new Part()
{
//Properties
}).ToList();
foreach (var item in parts)
{
play.Parts.Add(item);
}
var reviews = (from r in doc.XPathSelectElement(".//Play//Reviews").Nodes()
select new Review
{
//Properties
}).ToList();
for (int i = 0; i < reviews.Count(); i++)
{
PlayReviews pR = new PlayReviews()
{
Review = reviews[i],
Play = play,
//Properties
};
play.PlayReviews.Add(pR);
}
return play;
}
如果我通过Add()添加此“播放”,则将插入“播放”的每个子对象-不管是否已经存在。 由于我需要更新现有条目,因此我必须对此做一些事情。 我想这里的问题是我在XML中没有任何ID。
据我所知,我有以下选择:
目前,我正在实施选项1-但感觉不对。
我想要做的是更新数据库中已有的实体,并插入没有的实体。 我必须在附加/添加播放之前调用SaveChanges()吗? 必须有一个(相对)简单的解决方案。 如果有人可以在正确的方向上指导我,我将不胜感激。
好吧,既然还没有答案,我自己写一个。
对于那些想知道的人,我可以使用它-代码看起来很难看,我想性能会更差。 但是由于不会有太多的用户,而且无论如何我只会在晚上每天调用一次此方法,现在我可以接受。
我做了什么
好吧,我选择了选项2和3。
private Play UpdatePlay()
{
using (RepositoryContext context = new RepositoryContext())
{
HttpRequest http = new HttpRequest();
PlayRepository rep = new PlayRepository(context);
ActorRepository actRep = new ActorRepository(context);
ReviewsRepository revRep = new ReviewsRepository(context);
TheatreRepository insRep = new TheatreRepository(context);
PartRepository partRep = new PartRepository(context);
Parser p = new Parser();
XDocument doc = http.GetPlayInfo();
Theatre theatre = p.ParseTheatreInfo(doc);
List<Actor> actors = p.ParseActorInfo(doc);
List<PlayReviews> playReviews = p.ParseReviewsInfo(doc);
for (int i = 0; i < actors.Count; i++)
{
actors[i] = actRep.AddOrUpdate(actors[i]);
}
for (int i = 0; i < playReviews.Count; i++)
{
playReviews[i].Reviews = revRep.AddOrUpdate(playReviews[i].Reviews);
}
theatre = insRep.AddOrUpdate(theatre);
Play play = p.ParsePlayInfo(doc);
List<Part> parts = GetParts(play);
for (int i = 0; i < parts.Count; i++)
{
List<Actor> lec = (List<Actor>)parts[i].Actors;
for (int j = 0; j < lec.Count; j++)
{
lec[j] = actRep.AddOrUpdate(lec[j]);
}
}
play = rep.AddOrUpdate(play);
context.LoadProperty(play, o => o.Theatre);
context.LoadProperty(play, o => o.Actors);
context.LoadProperty(play, o => o.PlayReviewss);
context.LoadProperty(play, o => o.Parts);
rep.Save();
if (play.Theatre != theatre)
play.Theatre = theatre;
play = rep.AddParts(parts, play);
play = rep.AddActor(actors, play);
for (int i = 0; i < playReviews.Count; i++)
{
playReviews[i].Play = play;
playReviews[i] = revRep.AddPlayInformation(playReviews[i]);
}
rep.Save();
return play;
}
}
(顺便说一句,我刚刚意识到我以前忘记发布代码的这一部分...)
如您所见,Save()被调用两次-当您考虑AddOrUpdate()中发生的事情时,情况变得更糟:
public Actor AddOrUpdate(Actor entity)
{
Actor cur = context.Actors.Where(l => l.Name == entity.Name && l.Last_Name == entity.Last_Name).FirstOrDefault();
if (cur == null)
{
context.Actors.AddObject(entity);
return entity;
}
else
{
if (!entity.Mail.IsNullOrEmptyOrWhitespace() && cur.Mail != entity.Mail)
cur.Mail = entity.Mail;
//there are more of these...
return cur;
}
}
我不敢相信这是做到这一点的“正确”方法。 感觉和看起来都是错误的。 也许英孚也要怪
FirstEntityType first = new FirstEntityType();
first.Id = 2;
List<SecondType> list = CreateList(); //Let's say this returns a List with 10 elements
context.FirstEntityType.AddObject(first);
for (int i = 0; i < list.Count; i++)
{
list[i].First = first;
}
//just for arguments sake a second for
for (int i = 0; i < list.Count; i++)
{
context.SecondType.AddObject(list);
}
context.SaveChanges();
我还没有测试过这段特定的代码,但是从我的经验来看,我将为SecondType最终添加10个新条目,如果我没有记错的话,那么将为FirstEntityType添加11个新条目。
为什么? 为什么EF中没有这样一种机制:“嘿,请稍等-一样!”
我是否错误地认为EF应该像直接使用db一样表现? 在我的示例中,我添加了“ first”,因此我可以假定每当我使用“ first”时都会被引用。 (我真的希望我的示例能按描述的那样工作-既没有时间也没有测试的欲望)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.