使用超类型/子类型数据库优先模型插入MVC中的多个外键表

时间:2012-12-11 16:53:09

标签: asp.net-mvc entity-framework asp.net-mvc-4

我有两个超类型“实体”的子类型,即“家庭”和“涉及身体”。

我已经在我的数据库中对它们进行了如下所示的建模,并将它们自动生成到EF模型中(如下所示)。

数据库 enter image description here

edmx模型 enter image description here

使用MVC的默认脚手架我能够毫无问题地添加新的家庭。但是,当我尝试添加新的Involved Body时,我在尝试添加实体类型时遇到错误。

只有相关(据我所知)这两个子类型之间的区别在于,家庭的EntityType被硬编码为“Household”,而Involved Body的EntityType可以是除“Household”之外的任何EntityType “ - 这是用户从列表中选择的。

对于Involved Body,HTTP POST上的Create Action会抛出与tEntity和tEntityType之间的外键相关的错误,并且tEntityType为null。代码如下:

[HttpPost]
public ActionResult Create([Bind(Exclude = "entityID")]tEntity tentity            
                                                        , tInvolvedBody tinvolvedbody
                                                        , tAddress taddress
                                                        , tAddressEntity taddressentity
                                                        //, tEntityType tentitytype
                                                        , int entityTypeID
                                                        )
{

    #region entity type
    //find entity type from id
    var tentitytype = db.tEntityTypes.Find(entityTypeID);                     

    #endregion

    #region address
    //assume start date of involved body not needed for reporting
    taddressentity.startDate = DateTime.Now.Date;

    #endregion


    if (ModelState.IsValid)
    {

        db.tEntities.Add(tentity);
        db.tInvolvedBodies.Add(tinvolvedbody);
        db.tAddresses.Add(taddress);
        db.tAddressEntities.Add(taddressentity);

        db.SaveChanges();
        return RedirectToAction("Index");
    }

    //recreate viewbag for entityType dropdown
    var q = (
            from e in db.tEntityTypes
            where e.entityType != "Household"
            select e
        );

    ViewBag.entityTypeID = new SelectList(q, "entityTypeID", "entityType");
    return View(tinvolvedbody);
}

我尝试将tEntityType添加到create的参数列表中,但这会导致ModelState.IsValid返回false,因为所有对象的entityType都为null。

我还尝试使用以下方法将实体类型主动链接到其他每个对象:

tentity.tEntityType = tentitytype;
tinvolvedbody.tEntity.tEntityType = tentitytype;
taddressentity.tEntity.tEntityType = tentitytype;

以上操作最终会起作用,但它会为每个其他对象创建一个新的实体,即我在tEntity表中获得三个新行,一个是实体,一个链接到tInvolvedBody,一个链接到tAddressEntities。这毫无意义......

如何插入创建实体的新InvolvedBody,获取实体类型然后链接到AddressEntity联结表?

2 个答案:

答案 0 :(得分:1)

最后解决了这个问题。不确定从开发人员的角度来看答案是否“完美”,但它确实有效。

经过深入调试后,我意识到所涉及的主体和地址实体的导航属性都在寻找我假设将由实体对象提供的entitytypeID。

如果我直接使用显示的代码传递这些代码:

tinvolvedbody.tEntity.tEntityType = tentitytype;
taddressentity.tEntity.tEntityType = tentitytype;

......我最终得到了三个新的权利,并且所有{实体,涉及的机构,地址}之间都没有关系数据

有效的代码删除了新实体的显式添加,并依赖EF从Involved Body创建实体。然后,我使用新创建的entityID通过addressentity映射地址,如下所示:

[HttpPost]
public ActionResult Create([Bind(Exclude="entityID")]tEntity tentity
                                                    ,tInvolvedBody tinvolvedbody
                                                    ,tAddress taddress
                                                    ,tAddressEntity taddressentity
                                                    ,int entityTypeID
                                                    )
{

    #region entity type
    var t =
            (
                from e in db.tEntityTypes
                where (e.entityTypeID == entityTypeID)
                select e
            );

    tinvolvedbody.tEntity.tEntityType = t.First();
    #endregion

    #region address
    //assume start date of involved body not needed for reporting
    taddressentity.startDate = DateTime.Now.Date;

    #endregion

    if (ModelState.IsValid)
    {
        db.tInvolvedBodies.Add(tinvolvedbody);                
        db.tAddresses.Add(taddress);

        taddressentity.tEntity = db.tEntities.Find(tinvolvedbody.bodyID);

        db.tAddressEntities.Add(taddressentity);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

答案 1 :(得分:0)

您是否尝试过专门设置typeID?另外,根据我从你的模型中收集的内容,这个taddress是一个孩子的taddressentity?因此,为了输入外键,是否应该先插入它?

if (ModelState.IsValid)
    {
        tentity.entityTypeID = entityTypeID;
        db.tEntities.Add(tentity);

        tinvolvebody.bodyID= tentity.entityID
        db.tInvolvedBodies.Add(tinvolvedbody);

        taddressentity.entityID = tentity.entityID;
        db.tAddressEntities.Add(taddressentity);

        taddress.UPRN = taddressentity.UPRN;
        db.tAddresses.Add(taddress);



        db.SaveChanges();
        return RedirectToAction("Index");
    }