无法将空值插入可空字符串字段

时间:2016-08-06 00:41:45

标签: asp.net asp.net-mvc entity-framework asp.net-mvc-5 entity-framework-6

当前项目:

  • ASP.NET 4.5.2
  • MVC 5
  • EF 6
  • Fluent API,针对存储过程进行了调整

我可以在一个表中除了一组三个nvarchar(MAX)列之外的所有内容中插入空值,这会让我感到沮丧。

模特:

public string SpecialtyEquipment { get; set; }
public string EQAttachments { get; set; }
public string SpecialtySafetyTickets { get; set; }

Fluent API:

Jobs.Property(x => x.SpecialtyEquipment).IsOptional();
Jobs.Property(x => x.EQAttachments).IsOptional();
Jobs.Property(x => x.SpecialtySafetyTickets).IsOptional();

SQL Server 2012中的表格,它清楚地将所有三列显示为nvarchar(MAX)并且可以为空。由于这是代码优先,我从未直接触及数据库。

我的(减少)控制器:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> JobAdditional(JobAdditionalViewModel model) {
  Jobs job = await db.Jobs.FindAsync(model.Job.JobId);
  JobMap jobMap = new JobMap(model.Job, job);
  db.Entry(job).State = EntityState.Modified;
  await db.SaveChangesAsync();
  return RedirectToAction("JobDetail", new { id = model.Job.RecruiterJobId });
}

我的ViewModel:

public class JobAdditionalViewModel {
  public Jobs Jobs { get; set; } // to display most of the current job
  public JobModel Job { get; set; } // to edit a specific portion of the current job
}

我的表单模型:

public class JobModel {
  public Guid? JobId { get; set; }
  [DisplayName("Specialty Equipment (not on prior page)")]
  public string SpecialtyEquipment { get; set; }
  [DisplayName("Specialty Attachments (not on prior page)")]
  public string EQAttachments { get; set; }
  [DisplayName("Specialty Safety Tickets (not on prior page)")]
  public string SpecialtySafetyTickets { get; set; }
}

我的地图模型:

public JobMap(JobModel model, Jobs job) {
  job.SpecialtyEquipment = model.SpecialtyEquipment.Trim();
  job.EQAttachments = model.EQAttachments.Trim();
  job.SpecialtySafetyTickets = model.SpecialtySafetyTickets.Trim();
}

所有错误都标记了我的映射模型,当textarea中没有内容时,它们会标记三者中的任何一个 - 也就是说,如果它是一个什么都没有的值,或者是被修剪为空的空格

我已经尝试了所有“处理”无内容字符串的变体,似乎没有任何效果。每一次,无论我如何处理零内容(空textarea),我都会获得System.NullReferenceException

为了记录,这些都失败了:

= (string.IsNullOrEmpty(model.SpecialtyEquipment.Trim()) ? null : model.SpecialtyEquipment.Trim());
= (model.SpecialtyEquipment.Trim().Length == 0 ? null : model.SpecialtyEquipment.Trim());

我甚至尝试用null代替string.Empty,但无济于事。

事实上,唯一可行的方法是使用null;替换映射模型中等于之后的所有内容。是的,这是正确的 - 强制喂它零值:

= null;

不是尝试使用null作为一个选项的三元运算符,而是唯一能够实际工作的东西。

事实上,我在整个项目中分散了许多不同的可空列,我可以插入空值而没有任何问题。我所要做的就是将null转换为列类型的可空版本:

(Guid?)null;
(int?)null;
(decimal?)null;

它完美无缺。

但是由于你不能将null转换为可以为空的字符串,你如何处理呢?

2 个答案:

答案 0 :(得分:1)

您可以尝试使用string.IsNullOrWhiteSpace,并避免在字符串为空时调用Trim()

job.SpecialtyEquipment = string.IsNullOrWhiteSpace(model.SpecialtyEquipment) ? null : model.SpecialtyEquipment.Trim();

答案 1 :(得分:1)

如果NullReferenceException为空,此行会在model.SpecialtyEquipment.Trim()上抛出model.SpecialtyEquipment

= (string.IsNullOrEmpty(model.SpecialtyEquipment.Trim()) ? null : model.SpecialtyEquipment.Trim());

如果NullReferenceException为null,则此行会在model.SpecialtyEquipment.Trim()上抛出model.SpecialtyEquipment

= (model.SpecialtyEquipment.Trim().Length == 0 ? null : model.SpecialtyEquipment.Trim());

要再次将其分解,您将获得NullReferenceException(NRE),因为model.SpecialtyEquipment的值为null,现在您正在调用该空值的方法。您可以通过执行此操作来复制它

((string)null).Trim(); // will throw a NRE

这将是最佳解决方案

model.SpecialtyEquipment = string.IsNullOrWhiteSpace(model.SpecialtyEquipment) // an actual null/empty check without the possibility of a NRE
    ? null 
    : model.SpecialtyEquipment.Trim();

string.IsNullOrWhiteSpace

如果您使用的是不支持此方法的旧版本框架,请执行以下两种检查:

model.SpecialtyEquipment = model.SpecialtyEquipment == null || model.Trim().Length == 0 
    ? null 
    : model.SpecialtyEquipment.Trim();

这两个都可以防止因为检查null而抛出NRE,如果它为null则不对字符串执行操作。