Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 实体框架中的多态性_Asp.net Mvc_Entity Framework_Razor_Dynamic_Polymorphism - Fatal编程技术网

Asp.net mvc 实体框架中的多态性

Asp.net mvc 实体框架中的多态性,asp.net-mvc,entity-framework,razor,dynamic,polymorphism,Asp.net Mvc,Entity Framework,Razor,Dynamic,Polymorphism,具体的类(银行账户和信用卡)在控制器上不可见 我被这个问题缠住了 我正在使用这个网站上的例子: 视图 CreateUser: 如果选择了信用卡,它应该与用户类关联 图表 代码 用户控制器: [HttpPost] public ActionResult Create(User user)//The Watch above came from this user instance { if (ModelState.IsValid) {

具体的类(
银行账户
信用卡
)在控制器上不可见

我被这个问题缠住了

我正在使用这个网站上的例子:

视图

CreateUser

如果选择了
信用卡
,它应该与
用户
类关联

图表

代码

用户控制器

    [HttpPost]
    public ActionResult Create(User user)//The Watch above came from this user instance
    {
        if (ModelState.IsValid)
        {

            context.User.Add(user);
            context.SaveChanges();
            return RedirectToAction("Index");  
        }

        ViewBag.PossibleBillingDetail = context.BillingDetail;
        return View(user);
    }
User\\u CreateOrEdit.cshtml

    @model TPTMVC.Models.User
    @using TPTMVC.Models;

<script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.5.js" type="text/javascript"></script> 
<script type="text/javascript">

    $(document).ready(function () {
        $('.divbank').hide();
        $('input[type=radio]').live('change', function () { updateweather(); });
    });

    function updateweather() {
        //alert();
        if ($('input[type=radio]:checked').val() == 'Bank') {
            $('.divcard').fadeOut(1000);
            $('.divcard').hide();
            $('.divbank').fadeIn(1000);
        }
        else {
            $('.divbank').fadeOut(1000);
            $('.divbank').hide();
            $('.divcard').fadeIn(1000);
            }

    }
        </script>
    <div id="json"></div>

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
    <legend>User</legend>

        @Html.Partial("_CreateOrEdit", Model)

        <div ='none' class="divcard">
            <div class="editor-label">
                @Html.LabelFor(model => ((CreditCard)model.billingDetail).ExpiryMonth)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => ((CreditCard)model.billingDetail).ExpiryMonth)
                @Html.ValidationMessageFor(model => ((CreditCard)model.billingDetail).ExpiryMonth)
            </div>

             <div class="editor-label">
                @Html.LabelFor(model => ((CreditCard)model.billingDetail).ExpiryYear)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => ((CreditCard)model.billingDetail).ExpiryYear)
                @Html.ValidationMessageFor(model => ((CreditCard)model.billingDetail).ExpiryYear)
            </div> 
        </div>

        <div='none' class="divbank">
            <div class="editor-label">
                @Html.LabelFor(model => ((BankAccount)model.billingDetail).BankName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => ((BankAccount)model.billingDetail).BankName)
                @Html.ValidationMessageFor(model => ((BankAccount)model.billingDetail).BankName)
            </div>

             <div class="editor-label">
                @Html.LabelFor(model => ((BankAccount)model.billingDetail).Swift)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => ((BankAccount)model.billingDetail).Swift)
                @Html.ValidationMessageFor(model => ((BankAccount)model.billingDetail).Swift)
            </div> 
        </div>  
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

User\Create.cshtml

    @model TPTMVC.Models.User
    @using TPTMVC.Models;

<script src="http://ajax.microsoft.com/ajax/jQuery/jquery-1.5.js" type="text/javascript"></script> 
<script type="text/javascript">

    $(document).ready(function () {
        $('.divbank').hide();
        $('input[type=radio]').live('change', function () { updateweather(); });
    });

    function updateweather() {
        //alert();
        if ($('input[type=radio]:checked').val() == 'Bank') {
            $('.divcard').fadeOut(1000);
            $('.divcard').hide();
            $('.divbank').fadeIn(1000);
        }
        else {
            $('.divbank').fadeOut(1000);
            $('.divbank').hide();
            $('.divcard').fadeIn(1000);
            }

    }
        </script>
    <div id="json"></div>

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
    <legend>User</legend>

        @Html.Partial("_CreateOrEdit", Model)

        <div ='none' class="divcard">
            <div class="editor-label">
                @Html.LabelFor(model => ((CreditCard)model.billingDetail).ExpiryMonth)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => ((CreditCard)model.billingDetail).ExpiryMonth)
                @Html.ValidationMessageFor(model => ((CreditCard)model.billingDetail).ExpiryMonth)
            </div>

             <div class="editor-label">
                @Html.LabelFor(model => ((CreditCard)model.billingDetail).ExpiryYear)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => ((CreditCard)model.billingDetail).ExpiryYear)
                @Html.ValidationMessageFor(model => ((CreditCard)model.billingDetail).ExpiryYear)
            </div> 
        </div>

        <div='none' class="divbank">
            <div class="editor-label">
                @Html.LabelFor(model => ((BankAccount)model.billingDetail).BankName)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => ((BankAccount)model.billingDetail).BankName)
                @Html.ValidationMessageFor(model => ((BankAccount)model.billingDetail).BankName)
            </div>

             <div class="editor-label">
                @Html.LabelFor(model => ((BankAccount)model.billingDetail).Swift)
            </div>
            <div class="editor-field">
                @Html.EditorFor(model => ((BankAccount)model.billingDetail).Swift)
                @Html.ValidationMessageFor(model => ((BankAccount)model.billingDetail).Swift)
            </div> 
        </div>  
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
问题

单击“创建”按钮时,我得到以下结果:

我选择了一张
信用卡
,但结果是
BillingDetail
。我试着做一个演员,但我犯了一个错误,正如你所看到的

:(

为什么只有
BillingDetail
出现在
UserController

我的第一个解决方案
我认为这里有几件事不对:

  • 您没有坚持关注点分离原则。如果您提供的模型图是针对您的实体的,那么您不应该将它们用作前端模型。您的数据层和视图层应该有单独的模型——这使您可以将数据的设计方式与用户的交互方式解耦
  • 因此,如果我错了,请用户纠正我,但是您不能在网页数据中返回具体的服务器端对象。在这种情况下,您试图将
    BillingDetail
    ,一个c#类,转换为模型供您查看,然后随表单提交一起返回。据我所知,只能返回普通数据和表单字段在表单提交中。您可以让视图模型包含其他视图模型和具体类,但只能返回普通字段和包含普通字段的视图模型
  • 您正试图将基类强制转换为派生类。当您将派生类作为基类传递,然后在其他地方重新强制转换它时,这是可能的,但您不能将纯基类转换为更具体的对象。这就像试图将矩形强制转换为正方形一样
  • 解决方案方面,您应该这样做:

    • 信用卡
      银行账户
      创建两个单独的视图模型,每个视图模型都有各自的属性。(您应该对
      用户
      对象执行相同的操作,以便遵守SoC)
    • 使用模型填充视图,使用两个新视图模型代替
      BillingDetail
    • 提交表单时,将单选按钮用作控制器中的条件,以确定用户选择的付款类型,然后创建相应的对象,将视图模型属性映射到具体对象,将其添加到用户,然后保存

    虽然我同意Matt的观点,但使用视图模型通常是一个好主意,问题的直接原因在于

    ViewBag.PossibleBillingDetail = context.BillingDetail;
    
    这还包括
    BankAccount
    s,因此一些
    BillingDetail
    对象不能强制转换为
    CreditCard

    将线路更换为

    ViewBag.PossibleBillingDetail = context.BillingDetail.OfType<CreditCard>();
    
    ViewBag.PossibleBillingDetail=context.BillingDetail.OfType();
    
    您正在将一个
    用户
    对象传递给您的视图。该对象具有到
    账单详细信息
    的导航属性,可以是
    信用卡
    银行账户
    。您可以在视图
    (信用卡)模型
    (银行账户)中按此方式进行转换模型
    。创建时它会工作,因为您正在强制转换为null的实例,但如果您有非null实例,则会导致运行时错误,因为其中一个强制转换将失败

    若要修复此问题,您可以使用
    模型作为信用卡
    模型作为银行帐户
    ,然后在呈现相应编辑器之前检查它们是否为空。但是,您需要确定当您的用户想要更改付款方式时该怎么办

    当表单返回到控制器时,由于您的
    Create
    方法签名采用了
    User
    参数,因此默认的
    ModelBinder
    知道它应该实例化
    User
    。它很有能力做到这一点,但它无法解决如何处理
    FormCollect中出现的值与
    账单详细信息相关的ion

    对于继承,您不能依赖默认的
    ModelBinder
    。您需要找出最适合您的方法。以下是一些我发现很有用的参考资料:

    -但看看这里的所有其他解决方案

    下面是我的项目中的一些示例代码,可以让您了解:

    public ActionResult CreateOrEdit(FormCollection values)
    {
        //The FormCollection is either a Property or a Block
        BaseProperty model;
        if (values["PropertyTypeID"] != null)
        {
            //it must be a Property!
            Property property = new Property();
            TryUpdateModel(property);
            _Uow.PropertyRepository.InsertOrUpdate(property);
            model = property;
        }
        else
        {
            Block block = new Block();
            TryUpdateModel(block);
            _Uow.BlockRepository.InsertOrUpdate(block);
            model = block;
        }
        //etc....
    

    你能添加你的信用卡类别定义吗?道格,我添加了信用卡类别。格特·阿诺德,在做任何事情之前,我想感谢你的帮助,但你的建议不会改变结果。:(第1项说“不应该”,所以它是正确的,但不严格相关,因为它不会解决问题……第2项说“您不能在网页数据中返回具体的服务器端对象".这是严格正确的,但是默认的
    ModelBinder
    使它看起来像是你可以…所以你可以说一个…第3项击中了要害,最后一个要点是你的解决方案…现在你需要决定在哪里创建相应的对象。自定义模型绑定器还是在控制器中?是的,第1点更像是一个最佳实践,这是对他未来问题的先发制人的解决方法!我建议他使用AutoMapper或类似的对象创建。马特·福克斯·邓肯,你觉得我的第一个解决方案怎么样?是你的解决方案吗?科林,你觉得我的第一个解决方案怎么样?@Eduardoxvii。看起来不错。我会更改“收音机”的名称参数设置为更有意义的参数-例如“PaymentMethod”。它有效吗?
    public ActionResult CreateOrEdit(FormCollection values)
    {
        //The FormCollection is either a Property or a Block
        BaseProperty model;
        if (values["PropertyTypeID"] != null)
        {
            //it must be a Property!
            Property property = new Property();
            TryUpdateModel(property);
            _Uow.PropertyRepository.InsertOrUpdate(property);
            model = property;
        }
        else
        {
            Block block = new Block();
            TryUpdateModel(block);
            _Uow.BlockRepository.InsertOrUpdate(block);
            model = block;
        }
        //etc....