LINQ to SQL INSERT失败

时间:2009-08-25 22:15:25

标签: c# asp.net-mvc linq-to-sql repository-pattern

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

  

无法将值NULL插入   列'名称',表格   'EquipmentManufacturer';专栏   不允许空值。 INSERT失败。该   声明已被终止。

这个错误抱怨'Name'字段为null但不应该是这种情况。当我调试并逐步执行此集合时,[“名称”]具有我在表单上输入的值。

这是表create语句。

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>

这是我正在使用的Repository实现。

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 个答案:

答案 0 :(得分:3)

是因为你要两次调用.InsertOnSubmit(实体)吗?

您在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(实体)。

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

HTHS,
查尔斯

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

寻找答案的一些建议:

  • 使用SQL事件探查器跟踪INSERT语句,这可能会为您提供更多线索。

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

答案 3 :(得分:0)

我看到你没有使用'自动绑定'(或者你所谓的任何你接受你想要绑定的实体作为动作方法参数),而是(A)新建对象和(B)手动设置formCollection的“Name”属性。也许我看不出“EquipmentManufacturerID”被绑定在哪里了?

此EquipmentManufacturerID属性上的NULL失败了吗?