EF4 вставить сущность с дочерними элементами.Использование шаблона POCO T4 - PullRequest
0 голосов
/ 17 декабря 2010

Я буквально схожу с ума от этого.Я получаю из HTML данные об одном объекте "Отец", а также данные трех дочерних объектов.

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

Это мой код ModelBinder:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        DefaultModelBinder binder = new DefaultModelBinder();
        var estimate = (Estimate)binder.BindModel(controllerContext, bindingContext);

        estimate.Id = Guid.NewGuid();
        estimate.OwnerSociety = ModelBinderHelper.MapComplexType<OwnerSociety, int>(controllerContext, "OwnerSociety", int.Parse, c => c.IDOwnerSociety);
        estimate.EstimateType = ModelBinderHelper.MapComplexType<EstimateType, Guid>(controllerContext, "EstimateType", Guid.Parse, c => c.Id);
        estimate.Brand = ModelBinderHelper.MapComplexType<Brand, int>(controllerContext, "Brand", int.Parse, c => c.IDBrand);
        estimate.FromAccount = ModelBinderHelper.MapComplexType<User, int>(controllerContext, "FromAccount", int.Parse, c => c.IDUser);
        estimate.ManagerDirector = ModelBinderHelper.MapComplexType<User, int>(controllerContext, "ManagerDirector", int.Parse, c => c.IDUser);

        estimate.Projects.Add(new Project
        {
            StrategicPlanner = ModelBinderHelper.MapComplexType<User, int>(controllerContext, "StrategicPlanner_1", int.Parse, c => c.IDUser),
            Activity = ModelBinderHelper.MapComplexType<Activity, int>(controllerContext, "Activity_1", int.Parse, c => c.IDActivity),
            ProjectState = ModelBinderHelper.MapComplexType<ProjectState, int>(controllerContext, "ProjectState_1", int.Parse, c => c.IDProjectState),
            StartDate = DateTime.Now,
            Name = "XXX1",
            Brand = estimate.Brand,
            ProjectTypes = new ProjectTypes { IDProjectType = 1 },
            Consuntivo = 0,
            Order = 1
        });
        estimate.Projects.Add(new Project
        {
            StrategicPlanner = ModelBinderHelper.MapComplexType<User, int>(controllerContext, "StrategicPlanner_2", int.Parse, c => c.IDUser),
            Activity = ModelBinderHelper.MapComplexType<Activity, int>(controllerContext, "Activity_2", int.Parse, c => c.IDActivity),
            ProjectState = ModelBinderHelper.MapComplexType<ProjectState, int>(controllerContext, "ProjectState_2", int.Parse, c => c.IDProjectState),
            StartDate = DateTime.Now,
            Name = "XXX2",
            Brand = estimate.Brand,
            ProjectTypes = new ProjectTypes { IDProjectType = 1 },
            Consuntivo = 0,
            Order = 2
        });
        estimate.Projects.Add(new Project
        {
            StrategicPlanner = ModelBinderHelper.MapComplexType<User, int>(controllerContext, "StrategicPlanner_3", int.Parse, c => c.IDUser),
            Activity = ModelBinderHelper.MapComplexType<Activity, int>(controllerContext, "Activity_3", int.Parse, c => c.IDActivity),
            ProjectState = ModelBinderHelper.MapComplexType<ProjectState, int>(controllerContext, "ProjectState_3", int.Parse, c => c.IDProjectState),
            StartDate = DateTime.Now,
            Name = "XXX3",
            Brand = estimate.Brand,
            ProjectTypes = new ProjectTypes { IDProjectType = 1 },
            Consuntivo = 0,
            Order = 3
        });

        return estimate;
    }

Когда я пытаюсь просто присоединить мою отцовскую сущность, объявить ее и дочерние свойства как добавленные, я получаю «уже есть объект в objectstatemanager стот же ключ ".Если я пытаюсь вставить отцовскую сущность без childs, она работает.

Я попробовал другой «путь».Следующий код:

public Estimate CreateEstimate(Estimate toCreate)
    {
        var brand = Brands.First(c => c.IDBrand == toCreate.Brand.IDBrand);
        var estimateType = EstimateTypes.First(c => c.Id == toCreate.EstimateType.Id);
        var account = Users.First(c => c.IDUser == toCreate.FromAccount.IDUser);
        var manager = Users.First(c => c.IDUser == toCreate.ManagerDirector.IDUser);
        var owner = OwnerSocieties.First(c => c.IDOwnerSociety == toCreate.OwnerSociety.IDOwnerSociety);

        toCreate.Brand = brand;
        toCreate.EstimateType = estimateType;
        toCreate.FromAccount = account;
        toCreate.ManagerDirector = manager;
        toCreate.OwnerSociety = owner;

        foreach (var project in toCreate.Projects)
        {
            project.Activity = Activities.First(c => c.IDActivity == project.Activity.IDActivity);
            project.ProjectState = ProjectStates.First(c => c.IDProjectState == project.ProjectState.IDProjectState);
            project.StrategicPlanner = Users.First(c => c.IDUser == project.StrategicPlanner.IDUser);
            project.ProjectTypes = _entities.ProjectTypes.First();
        }

        _entities.EstimateSet.AddObject(toCreate);

        return toCreate;
    }

Но он не работает, сообщая мне, что «INSERT для таблицы« Деятельности »не выполняется, поскольку столбец« Имя »не может быть пустым».Но на самом деле не следует ничего вставлять в таблицу Activity, на самом деле я получаю элементы Activity из БД и использую их.

Забавно, работает следующий код:

public Estimate CreateEstimate(Estimate toCreate)
    {
        var estimate = new Estimate();

        var brand = Brands.First(c => c.IDBrand == toCreate.Brand.IDBrand);
        var estimateType = EstimateTypes.First(c => c.Id == toCreate.EstimateType.Id);
        var account = Users.First(c => c.IDUser == toCreate.FromAccount.IDUser);
        var manager = Users.First(c => c.IDUser == toCreate.ManagerDirector.IDUser);
        var owner = OwnerSocieties.First(c => c.IDOwnerSociety == toCreate.OwnerSociety.IDOwnerSociety);

        estimate.Id = toCreate.Id;
        estimate.Brand = brand;
        estimate.EstimateType = estimateType;
        estimate.FromAccount = account;
        estimate.ManagerDirector = manager;
        estimate.OwnerSociety = owner;
        estimate.Date = toCreate.Date;
        estimate.Subject = toCreate.Subject;
        estimate.Status = toCreate.Status;
        estimate.Language = toCreate.Language;

        foreach (var project in toCreate.Projects)
        {
            var project1 = new Project();
            project1.Activity = Activities.First(c => c.IDActivity == project.Activity.IDActivity);
            project1.ProjectState = ProjectStates.First(c => c.IDProjectState == project.ProjectState.IDProjectState);
            project1.StrategicPlanner = Users.First(c => c.IDUser == project.StrategicPlanner.IDUser);
            project1.StartDate = project.StartDate;
            project1.Name = project.Name;
            project1.Brand = brand;
            project1.ProjectTypes = _entities.ProjectTypes.First();
            estimate.Projects.Add(project1);
        }

        _entities.EstimateSet.AddObject(estimate);

        return toCreate;
    }

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

ORM должен облегчить мне задачу написания тонн кода для операций CRUD, но, похоже, это не так.

Кто-нибудь может мне помочь?

1 Ответ

1 голос
/ 17 декабря 2010

У меня была точно такая же проблема, и у меня были те же проблемы при попытке использовать EF в отключенном сценарии.И я решил это так же, как и вы: перезагрузите объект и «переиграйте» изменения в доменном объекте (хотя вы должны применить хитрость, чтобы заставить работать оптимистичный параллелизм).Это был единственный способ заставить его работать.

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

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

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