【问题标题】:How to handle optional Foreign Key constraint error in One to Many relationship如何处理一对多关系中的可选外键约束错误
【发布时间】:2018-02-04 17:01:30
【问题描述】:

我是 ASP.Net MVC 5 的初学者,目前遇到了 Fluent API 问题。我有一个推荐类,它可以与 Coverletter 类有一对多的关系。有时 Rererral 行可能存在不带求职信(我认为是 0..*)。

流畅的 API:

//// one cover letter can be there in many referral request
dBModelBuilder.Entity<CoverLetter>()
    .HasMany(u => u.Referrals)
    .WithOptional(u => u.CoverLetter)
    .HasForeignKey(u => u.CoverLetterId);

推荐模型:

public class Referral
{
    [Key]
    public int ReferralId { get; set; }
    // I added "?" to make FK Optional
    public int? CoverLetterId { get; set; }
    public virtual CoverLetter CoverLetter { get; set; }
}

ReferralViewModel:

public class ReferralViewModel
{
    public int ReferralViewModelId { get; set; }
    [Display(Name = "Cover Letter")]
    public int CoverLetterId { get; set; }
    public IEnumerable<CoverLetter> CoverLetters { get; set; }
}

控制器动作:

[HttpPost]
public ActionResult Create(ReferralViewModel viewModel)
{
    var candidateId = User.Identity.GetUserId();
    var referral = new Referral
    {
        CoverLetterId = viewModel.CoverLetterId
    };
   // I get exception here
    _context.Referrals.Add(referral);
    _context.SaveChanges();
    return RedirectToAction("ReferralCenter");
}

问题 当我没有从 UI 中选择任何求职信时,我的 viewModel 中的 CoverLetter ID 为 0。而且我认为由于在 DB 中没有 ID 为 0 的求职信,因此我得到了 DB Contraint Exception。

例外:

{"INSERT 语句与 FOREIGN KEY 约束冲突 \"FK_dbo.Referrals_dbo.CoverLetters_CoverLetterId\"。冲突 发生在数据库“aspnet-Bridge-20170730012232”、表中 \"dbo.CoverLetters\",列 'CoverLetterId'。\r\n该语句有 已终止。"}

为了使 FK 成为可选,我做了两个步骤

一个。添加 ”?”在模型属性中

b.在 Fluent API 中添加了“HasOptional”。

修复:

如果我没有选择任何 CoverlLetter,那么在提交表单时,我希望 CoverLetter ID 为 NULL 而不是零。

【问题讨论】:

  • 您在视图模型中的CoverLetterId 属性需要为int?(可为空)
  • @StephenMuecke:先生,如果它是字符串,那么我不必添加“?”对吧?,只是因为字符串没有用“空字符串”自动初始化,所以它们保留了 NULL 值。但如果是整数,默认情况下它们会自动初始化为 0。
  • A string 已经可以为空,因此您无需执行任何操作。但是因为它的int 你需要让它可以为空
  • @StephenMuecke:这消除了我的疑问。因为在另外一个地方我有可选的 FK 关系,而且它总是工作得很好。我刚才检查了。它是字符串类型的“ApplicationUserID”(框架开箱即用)所以“?”不需要。 :)

标签: sql-server asp.net-mvc entity-framework asp.net-mvc-5 ef-fluent-api


【解决方案1】:

在控制器中更改求职信 ID 分配

CoverLetterId = viewModel.CoverLetterId == 0 ? null : viewModel.CoverLetterId;

你也可以做

public int CoverLetterId { get; set; }

更改为 public int? CoverLetterId { get; set; }ReferralViewModel

然后,在控制器中你将不得不使用额外的检查

CoverLetterId = viewModel.CoverLetterId.HasValue ? ((viewModel.CoverLetterId.Value == 0) ? null : viewModel.CoverLetterId.Value) : null

如果你知道你要在HttpPost中从前端传递0,并且不会让viewModel.CoverLetterId取它的默认值,你可以直接使用。

CoverLetterId = (viewModel.CoverLetterId.Value == 0) ? null : viewModel.CoverLetterId.Value

【讨论】:

  • 您不需要在最后一行代码中进行“附加检查”!
  • 它不会是'0'(除非它是恶意用户)所以没有意义
  • @Stephen 好的,明白了。但网站确实有恶意用户。尽管合并了您的评论,但在答案中添加了一条声明。
  • 是的,如果您不希望它是恶意用户,则保存数据(抛出异常):)
猜你喜欢
  • 2013-03-12
  • 2021-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-20
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
相关资源
最近更新 更多