gpt4 book ai didi

asp.net-mvc - Entity Framework 中的多态性

转载 作者:行者123 更新时间:2023-12-02 00:04:14 25 4
gpt4 key购买 nike

具体类(BankAccountCreditCard)在 Controller 上不可见。

我被这个问题困住了。

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

http://weblogs.asp.net/manavi/archive/2010/12/28/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt.aspx

观点

CreateUser:

如果选择了 CreditCard,它应该关联到 User 类。

Create User

图表

Class Diagram

代码

用户 Controller :

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

用户\_CreateOrEdit.cshtml:

enter image description here

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>

类代码:

namespace TPTMVC.Models{
public class BillingDetail
{
[Key]
[ForeignKey("user")]
public int UserID { get; set; }
public string Owner { get; set; }
public string Number { get; set; }
public virtual User user { get; set; }
}}

namespace TPTMVC.Models{
public class User
{
public int UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }

public virtual BillingDetail billingDetail { get; set; }
}}
namespace TPTMVC.Models{
[Table("BankAccounts")]
public class BankAccount:BillingDetail
{
public string BankName { get; set; }
public string Swift { get; set; }
}}
namespace TPTMVC.Models{
[Table("CreditCards")]
public class CreditCard:BillingDetail
{
public int CardType { get; set; }
public string ExpiryMonth { get; set; }
public string ExpiryYear { get; set; }
}}

问题

当我点击创建按钮时,我得到了这个结果:

Watch

我选择了一张 CreditCard,但结果是 BillingDetail。如您所见,我尝试进行转换,但出现错误。

:(

为什么只有 BillingDetail 出现在 UserController 上?

我的第一个解决方案

[HttpPost]
public ActionResult Create(User user, CreditCard card, BankAccount bank, String Radio)
{
//String teste=formCollection["Radio"];
if (ModelState.IsValid)
{
switch (Radio)
{
case "CredCard":
user.billingDetail = card;
break;
case "Bank":
user.billingDetail = bank;
break;
}
context.User.Add(user);
context.SaveChanges();
return RedirectToAction("Index");
}

ViewBag.PossibleBillingDetail = context.BillingDetail;
return View(user);
}

最佳答案

您正在将一个 User 对象传递给您的 View 。这有一个指向 BillingDetail 的导航属性,它可以是 CreditCardBankAccount。您在 View (CreditCard)model(BankAccount)model 中像这样转换它。它会在您创建时起作用,因为您正在转换一个 null 实例,但是当您有一个非 null 实例时它会导致运行时错误,因为其中一个转换会失败。

要解决此问题,您可以使用 model as CreditCardmodel as BankAccount 然后在呈现适当的编辑器之前检查它们是否为空。但是您需要弄清楚当您的用户想要更改付款方式时该怎么做。

当表单返回到 Controller 时,因为您的 Create 方法签名采用了一个 User 参数,默认的 ModelBinder 知道它应该实例化一个 User。它完全有能力做到这一点,但无法确定如何处理 FormCollection 中出现的与 BillingDetail 相关的值。

通过继承,您不能依赖默认的 ModelBinder。您需要找出最适合您的方法。以下是我认为有用的一些引用资料:

Get an understanding of ModelBinding

Custom model binders - one person's opinion

The solution I went with - 但也要看看这里的所有其他解决方案!

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

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....

关于asp.net-mvc - Entity Framework 中的多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19434965/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com