C# 实体框架-更新没有Id的实体

C# 实体框架-更新没有Id的实体,c#,entity-framework,C#,Entity Framework,我在网上找到了很多问题和文章,但没有一篇真正解决了我的问题 我的模型如下所示(我将所有非基本属性分条): 每天都会更新“Play”(通过包含信息的XML文件) 内部播放解析播放信息(XDocument文档) { Play Play=(来自文档子体(“Play”)中的p) 选择新剧本 { 剧院=新剧院 { //性质 }, //性质 LastUpdate=DateTime.Now }).SingleOrDefault(); var actors=(来自doc.XPathSelectElement(

我在网上找到了很多问题和文章,但没有一篇真正解决了我的问题

我的模型如下所示(我将所有非基本属性分条):

每天都会更新“Play”(通过包含信息的XML文件)

内部播放解析播放信息(XDocument文档)
{
Play Play=(来自文档子体(“Play”)中的p)
选择新剧本
{
剧院=新剧院
{
//性质
},
//性质
LastUpdate=DateTime.Now
}).SingleOrDefault();
var actors=(来自doc.XPathSelectElement(“.//Play//actors”).Nodes()中的
选择新讲师()
{
//性质
});
var parts=(来自doc.XPathSelectElement(“.//Play//parts”).Nodes()中的p)
选择新零件()
{
//性质
}).ToList();
foreach(部分var项目)
{
play.Parts.Add(项目);
}
var reviews=(来自doc.XPathSelectElement(“.//Play//reviews”).Nodes()中的r)
选择新评论
{
//性质
}).ToList();
for(int i=0;i
如果我通过add()添加这个“play”,则将插入play的每个Childobject——不管是否已经存在。因为我需要更新现有的条目,所以我必须做一些事情。我想这里的问题是我在XML中没有Id

据我所知,我有以下选择:

  • 添加/更新my中的子实体 PlayRepositories添加方法
  • 改写 ParsePlayInfo()以便获取所有 首先,添加或更新子实体 然后创作一部新剧。 我唯一的问题是 我希望ParsePlayInfo()是 坚持下去,我可以工作 围绕着这个
  • 创建多个 解析方法(例如ParseActors()) 让他们在我的房间里玩 控制器(我正在使用ASP.net MVC) 在所有东西都被解析和添加之后
  • 目前我正在实施选项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;
        }
    }
    
    我不敢相信这是“正确”的方法。 它感觉和看起来都不对。也许EF也应该受到责备,拿吧

    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();
    
    FirstEntityType first=新的FirstEntityType();
    第一,Id=2;
    List=CreateList()//假设它返回一个包含10个元素的列表
    context.FirstEntityType.AddObject(第一个);
    for(int i=0;i
    我还没有测试过这段特定的代码,但根据我的经验,SecondType将有10个新条目,如果我没有错的话,FirstEntityType将有11个条目

    为什么??为什么EF中没有一个机制会说“嘿,等等,这些都是一样的!”

    我是否认为EF的行为应该像我直接使用db那样错误?在我的示例中,我添加了“first”,这样我就可以假设每当我使用“first”时,它都会被引用。
    (我真的希望我的示例能如所述工作-没有时间也不想测试它)

    不,FirstEntityType不会有11个条目,只有数据库中的一个条目。只要您在一个ObjectContext中,在向上下文添加对象时,将保留标识。但是,当您第二次执行此代码时(在新上下文中),您确实会得到第二个FirstEntityType(或者当FirstEntityType.id是非自动递增主键时出现DABASE异常)。所以:实体框架实际上说:“它们是相同的!”,但这并不是因为相同的id字段,而是因为AddObject创建了一个(临时)EntityKey,它在一个ObjectContext中唯一地标识对象。我希望我仍然有那个代码,因为我做了类似的事情,并最终得到了许多条目。由于所有内容都很好地包装在一个using(context){}中,我非常确定我使用了相同的上下文。也许是不同的原因导致了这种行为,或者是我把事情搞砸了。过了一段时间,我真的很沮丧,想把工作做完。如果我有时间,也许我会做一些测试。很高兴看到有人读了这一切:)
    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();