LINQ to SQL INSERT失败
当我尝试使用LINQ to SQL插入新记录 时,我遇到了一个非常令人沮丧的问题。如果我单步执行此代码,有时会插入新记录 ,但大多数情况下不会。当它失败时,我看到以下错误。LINQ to SQL INSERT失败
无法插入NULL值插入 列 '名称',表 'EquipmentManufacturer';列确实是 不允许有空值。 INSERT失败。 声明已被终止。
这个错误是抱怨'姓名'字段为空,但不应该是这种情况。当我调试并逐步完成这个集合时[[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>
这是我正在使用的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)); }
}
}
是否因为您正在调用.InsertOnSubmit(实体)两次?
你曾经在新的()
public virtual T New()
{
T entity = Activator.CreateInstance<T>();
GetTable.InsertOnSubmit(entity);
return entity;
}
在.insert()这样
public virtual void Insert(T entity)
{
GetTable.InsertOnSubmit(entity);
}
我个人取下新的GetTable.InsertOnSubmit(实体)()再次调用它,然后方法。
原因是我认为对于存储库的用户来说,明确地插入实体会更好,而不是每次创建新实体时都会自动设置插入。
HTHS,
查尔斯
根据我的经验,这类问题通常来自映射配置中的错误。
寻找答案的一些建议:
使用SQL事件探查器跟踪的INSERT语句,这可能会给你更多的线索。
再次检查EquipmentManufacturer类的映射,名称可能未正确映射。将这些信息包含在您的问题中,因为它可以更好地了解问题。
我看,你是不是使用了“自动绑定”(或者无论你怎么称呼它,在那里你接受实体想要绑定的动作方法参数),但代替(A)newing对象和(B)手动设置formCollection的“Name”属性。也许我没有看到“EquipmentManufacturerID”被绑定在哪里?
此EquipmentManufacturerID属性是否为NULL失败?
我就遇到了这个问题,因为我已经在我的.dbml *文件Ling2SQL设置Auto Generated Value
选项true
;我将其更改为false
,错误消失。这是一个简单的错误,但它让我永远找到,因为我没有故意将值设置为true
。
这似乎解决了我的问题,但我不太确定为什么。如果我从Repository New方法注释掉GetTable.InsertOnSubmit(实体),它会起作用。如果我在Repository New方法中留下InsertOnSubmit调用,并在控制器中注释掉reposManu.Insert(entity)调用,它将失败。 – MHinton 2009-08-26 13:12:57
根据你刚才所说的判断,当你调用.InsertOnSubmit(entity)时,它需要一个对象的副本来保存它。因此,当你打电话给.InsertOnSubmit打上新的EquipmentManufacturer品牌时,它会尝试插入一个不包含任何值的副本,因此它会因数据库限制而失败。 – Charlino 2009-08-26 19:49:46
谢谢,这实际上是有道理的。 – MHinton 2009-08-27 00:48:57