繁体   English   中英

实体框架-更新没有ID的实体

[英]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. 在我的PlayRepositories Add-Method中添加/更新子实体
  2. 重组并重写ParsePlayInfo(),以便首先获取所有子实体,添加或更新它们, 然后创建一个新的Play。 我在这里唯一的问题是我希望ParsePlayInfo()对持久性不了解,我可以通过以下方法解决此问题:
  3. 创建了多个解析方法(例如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;
    }
}

(顺便说一句,我刚刚意识到我以前忘记发布代码的这一部分...)

如您所见,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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM