带有子项的EF4插入实体。使用POCO T4模板

时间:2010-12-17 10:35:39

标签: c# .net model-view-controller entity-framework-4

我真的对此感到疯狂。我从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;
    }

当我尝试简单地附加我的父实体时,声明它并将子属性声明为Added,我得到&#34;在objectstatemanager中已经有一个对象具有相同的键&#34;。如果我尝试插入没有子节点的父实体,它就可以工作。

我尝试了另一种&#34;方式&#34;。以下代码:

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;
    }

但它不起作用,告诉我&#34; INSERT on table&#34; Activities&#34;失败,因为列&#34;名称&#34;不能成为&#34;。但它确实不应该在Activity表中插入任何内容,实际上我正在从DB中检索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 个答案:

答案 0 :(得分:1)

我遇到了完全相同的问题,并且在断开连接的场景中尝试使用EF时遇到了同样的问题。我以与你一样的方式解决了它:重新加载对象,并“重放”域对象上的更改(你必须应用一个技巧来使乐观并发工作)。这是我找到的唯一方法。

使这项工作的另一种方法是将原始实体与修改后的实体一起发送。然后您不必重新加载它,只需附加原始实体并重播更改。但是如果你发送两次所有数据,我不确定开销,不太喜欢。

任何其他方式,只是失败,崩溃,因为它似乎混淆了上下文,即使它们已经被处理掉了。