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

时间:2010-06-08 19:59:57

标签: c# entity-framework

我在这里找到了很多关于SO和文章的问题,但没有一个问题真正解决了我的问题。

我的模型看起来像这样(我镶边了所有非必要的属性): alt text http://i47.tinypic.com/244p6qh.jpg

每天都会“更新”“播放”(通过包含信息的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()添加此“play”,则会插入每个Childobject of Play - 无论是否已存在某些。由于我需要更新现有条目,我必须对此做些什么。我想这里的问题是我在XML中没有Id。

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

  1. 添加/更新我的子实体 PlayRepositories Add-Method
  2. 重组和重写 ParsePlayInfo()使得得到所有 子实体首先添加或更新 他们和然后创建一个新的Play。 我在这里遇到的唯一问题是 我想要ParsePlayInfo() 坚持无知,我可以工作
  3. 创建多个 解析方法(例如ParseActors()) 并指派他们玩我的 控制器(我使用的是ASP.net MVC) 解析并添加所有内容后
  4. 目前我正在实施选项1 - 但感觉不对。

    我想要做的是更新数据库中已有的实体并插入不存在的新实体。 在附加/添加播放之前,是否必须调用SaveChanges()?必须有(相对)简单的解决方案。 如果有人能指导我在这个方向上朝着正确的方向前进,我会很感激。

1 个答案:

答案 0 :(得分:1)

好吧,既然没有答案,我会自己写一个。

对于那些想知道的人,我让它发挥作用 - 代码看起来很丑陋,我想性能更糟。但是因为不会有很多用户,而且这种方法每天只会被调用一次,所以我现在很好用。

我做了什么?

好吧,我选择了选项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;
    }
}

我无法相信这是“正确”的方式。 感觉和看起来都错了。也许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();

我没有测试过这段特殊的代码,但从我的经验来看,我最终将为SecondType添加10个新条目,如果我对FirstEntityType没有错误11。

为什么呢?为什么EF中没有一种机制可以说“嘿,等一下 - 这些都是一样的!”

如果我直接使用数据库,EF应该表现得如此错误吗?在我的例子中,我添加了“first”,所以我可以假设每当我使用“first”时它都被引用。 (我真的希望我的例子按照描述的方式工作 - 没有时间也没有测试它的愿望)