5

尝试使用 LINQ to SQL 插入新记录时,我遇到了一个非常令人沮丧的问题。如果我单步执行此代码,有时它会插入新记录,但大多数时候不会。当它失败时,我看到以下错误。

无法将值 NULL 插入到列“名称”、表“设备制造商”中;列不允许空值。插入失败。该语句已终止。

此错误抱怨“名称”字段为空,但事实并非如此。当我调试并单步执行此集合时,["Name"] 具有我在表单中输入的值。

这是表创建语句。

CREATE TABLE [EquipmentManufacturer] (
  [EquipmentManufacturerID] [int] IDENTITY(1,1) NOT NULL,
  [Name] [nvarchar](50) NOT NULL,

 CONSTRAINT [PK_EquipmentManufacturer] PRIMARY KEY CLUSTERED 
 (
    [EquipmentManufacturerID] ASC
 ) ON [PRIMARY]
) ON [PRIMARY]

这是我试图添加新记录的 ASP.NET MVC 控制器和创建操作。

public partial class EquipmentManufacturerController : Controller
{
  private IRepository<EquipmentManufacturer> reposManu;

  // POST: /EquipmentManufacturer/Create
  [AcceptVerbs(HttpVerbs.Post)]
  public virtual ActionResult Create(FormCollection collection)
  {
    EquipmentManufacturer entity = reposManu.New();
    try
    {
      //HACK: Something screwy is going on here the entity oject doesn't always get updated correctly
      //UpdateModel(entity);

      entity.Name = collection["Name"];
      reposManu.Insert(entity);
      reposManu.SubmitChanges();

      return RedirectToAction("Details", new { id = entity.EquipmentManufacturerID });
    }
    catch (RulesException ex)
    {
      ex.AddModelStateErrors(ModelState, "EquipmentManufacturer");
      return ModelState.IsValid ? RedirectToAction("Create")
        : (ActionResult)View();
    }
  }
}

这是 Create.aspx 视图。

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Create</h2>

    <%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>

    <% using (Html.BeginForm()) {%>

        <fieldset>
            <legend>Fields</legend>
            <p>
                <label for="Name">Name:</label>
                <%= Html.TextBox("Name") %>
                <%= Html.ValidationMessage("Name") %>
            </p>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>

    <% } %>
    <%= Html.ClientSideValidation<EquipmentManufacturer>() %>

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

</asp:Content>

这是我正在使用的存储库实现。

public class Repository<T> : IRepository<T> where T : class
{
  public IDataContext DC { get; set; }

  public Repository(IDataContext dataContext)
  {
      DC = dataContext;
  }

  /// <summary>
  /// Return all instances of type T.
  /// </summary>
  /// <returns></returns>
  public IEnumerable<T> All()
  {
      return GetTable;
  }

  /// <summary>
  /// Return all instances of type T that match the expression exp.
  /// </summary>
  /// <param name="exp"></param>
  /// <returns></returns>
  public IQueryable<T> Find(Expression<Func<T, bool>> exp)
  {
      return GetTable.Where<T>(exp);
  }

  /// <summary>See IRepository</summary>
  /// <param name="exp"></param>
  /// <returns></returns>
  public T Single(Expression<Func<T, bool>> exp)
  {
      return GetTable.SingleOrDefault(exp);
  }

  /// <summary>See IRepository</summary>
  /// <param name="exp"></param>
  /// <returns></returns>
  public T First(Expression<Func<T, bool>> exp)
  {
      return GetTable.First(exp);
  }

  /// <summary>See IRepository</summary>
  /// <param name="entity"></param>
  public virtual void Delete(T entity)
  {
      DC.Context.GetTable<T>().DeleteOnSubmit(entity);
  }

  /// <summary>
  /// Create a new instance of type T.
  /// </summary>
  /// <returns></returns>
  public virtual T New()
  {
      T entity = Activator.CreateInstance<T>();
      GetTable.InsertOnSubmit(entity);
      return entity;
  }

  /// <summary>
  /// Adds an insance T.
  /// </summary>
  /// <returns></returns>
  public virtual void Insert(T entity)
  {
      GetTable.InsertOnSubmit(entity);
  }

  /// <summary>
  /// Update entity.
  /// </summary>
  /// <returns></returns>
  public virtual void Update(T entity)
  {
      DC.Context.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, entity);
  }

  /// <summary>See IRepository</summary>
  public void SubmitChanges()
  {
      DC.SubmitChanges();
  }

  private string PrimaryKeyName
  {
      get { return TableMetadata.RowType.IdentityMembers[0].Name; }
  }

  private System.Data.Linq.Table<T> GetTable
  {
      get { return DC.Context.GetTable<T>(); }
  }

  private System.Data.Linq.Mapping.MetaTable TableMetadata
  {
      get { return DC.Context.Mapping.GetTable(typeof(T)); }
  }

  private System.Data.Linq.Mapping.MetaType ClassMetadata
  {
      get { return DC.Context.Mapping.GetMetaType(typeof(T)); }
  }
}
4

4 回答 4

3

是因为您两次调用 .InsertOnSubmit(entity) 吗?

你在 New() 中调用它一次

public virtual T New()
{
    T entity = Activator.CreateInstance<T>();
    GetTable.InsertOnSubmit(entity);
    return entity;
}

然后再次在 .Insert()

public virtual void Insert(T entity)
{
    GetTable.InsertOnSubmit(entity);
}

我个人会从 New() 方法中删除 GetTable.InsertOnSubmit(entity) 。

原因是我认为存储库的用户最好专门插入实体,而不是在每次创建新实体时自动设置为插入。

HTH,
查尔斯

于 2009-08-26T04:45:07.893 回答
1

我遇到了这个问题,因为我已将Auto Generated Value*.dbml Ling2SQL 文件中的选项设置为true;我将其更改为false,错误消失了。这是一个简单的错误,但我花了很长时间才找到,因为我没有故意将值设置为true.

于 2011-12-26T08:38:05.273 回答
0

以我的经验,这类问题通常来自映射配置中的错误。

寻找答案的一些建议:

  • 使用 SQL Profiler 跟踪 INSERT 语句,这可能会为您提供更多线索。

  • 仔细检查 EquipmentManufacturer 类的映射,名称可能未正确映射。在您的问题中包含该信息,因为它可以更好地了解问题。

于 2009-08-26T00:41:09.023 回答
0

我看到您没有使用“自动绑定”(或您所称的任何名称,您接受要绑定的实体作为操作方法参数),而是(A)更新对象并(B)设置其“手动从 formCollection 中获取“名称”属性。也许我看不到“EquipmentManufacturerID”的绑定位置?

此 EquipmentManufacturerID 属性是否为 NULL 失败?

于 2009-08-26T00:59:47.117 回答