Entity Framework - обновление сущностей без идентификатора - PullRequest
2 голосов
/ 08 июня 2010

Я нашел много вопросов здесь о SO и статьях по всему Интернету, но ни один из них не решал мою проблему.

Моя модель выглядит следующим образом (я зачеркнул все несущественные свойства): альтернативный текст http://i47.tinypic.com/244p6qh.jpg

Ежедневно "Play" обновляется (через 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 - независимо от того, существуют ли уже некоторые. Так как мне нужно обновить существующие записи, я должен что-то с этим сделать. Думаю, проблема в том, что у меня нет идентификатора в XML.

Насколько я могу судить, у меня есть следующие опции:

  1. добавить / обновить дочерние объекты в моем PlayRepositories Add-Method
  2. реструктурировать и переписать ParsePlayInfo (), чтобы получить все сначала дочерние объекты, добавьте или обновите их и , а затем создать новую игру. Единственная проблема, которую я имею здесь, состоит в том, что Я хотел, чтобы ParsePlayInfo () был упорство невежественное, я мог работать вокруг этого на
  3. создание нескольких методы разбора (например, ParseActors ()) и назначить их играть в моем контроллер (я использую ASP.net MVC) после того как все было проанализировано и добавлено

В настоящее время я реализую вариант 1, но он кажется неправильным.

Что я хочу сделать, это обновить сущности, которые уже есть в базе данных, и вставить новые, которых нет. Нужно ли вызывать SaveChanges (), прежде чем я присоединяю / добавляю Play? Должно быть (относительно) простое решение. Я был бы признателен, если бы кто-то мог направить меня в правильном направлении в этом.

1 Ответ

1 голос
/ 15 июня 2010

Ну, поскольку ответа пока нет, я сам напишу.

Для тех, кому интересно, я получил его на работу - код выглядит ужасно чертовски, и я думаю, что производительность еще хуже.Но так как пользователей будет не так много, и этот метод будет вызываться только один раз в день ночью, мне все равно сейчас это хорошо.

Что я сделал?

Ну, я пошел сВарианты 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();

Я не тестировал этот конкретный фрагмент кода, но из того, что я испытал, я получу 10 новых записей для SecondType, а если нетнеправильный 11 для FirstEntityType.

Почему?Почему в EF нет механизма, который говорит: «Эй, подожди минутку - это одно и то же!»В моем примере я добавил «first», чтобы предположить, что всякий раз, когда я использую «first», на него ссылаются.(Я действительно надеюсь, что мой пример работает так, как описано - у меня нет ни времени, ни желания его протестировать)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...