【问题标题】:EF4 insert entity with childs. Using POCO T4 templateEF4 插入带有子实体的实体。使用 POCO T4 模板
【发布时间】:2010-12-17 10:35:38
【问题描述】:

我真的要疯了。我从 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 中已经有一个具有相同键的对象”。如果我尝试插入没有孩子的父亲实体,它会起作用。

我尝试了另一种“方式”。以下代码:

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

但它不起作用,告诉我“在表“活动”上插入失败,因为列“名称”不能为空”。但它真的不应该在 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 操作编写大量代码的痛苦,但似乎并非如此。

谁能帮帮我?

【问题讨论】:

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


    【解决方案1】:

    我遇到了完全相同的问题,并且在尝试在断开连接的情况下使用 EF 时遇到了完全相同的痛苦。我以与您相同的方式解决了它:重新加载对象,并“重放”域对象上的更改(尽管您必须应用一个技巧来使乐观并发工作)。这是我发现让它发挥作用的唯一方法。

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

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

    【讨论】:

    • 这不是更新场景,这是插入场景。我创建的存根用于父对象和子对象所需的 FK。无论如何,它必须以这种方式工作似乎很奇怪。
    • 插入场景也是同样的问题
    猜你喜欢
    • 1970-01-01
    • 2011-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-28
    • 2011-12-16
    • 1970-01-01
    相关资源
    最近更新 更多