LINQ to SQL 插入失败
尝试插入新记录时,我遇到了一个非常令人沮丧的问题 使用 LINQ to SQL。如果我单步执行此代码,有时它会插入新记录 但大多数时候并非如此。当它失败时,我看到以下错误。
无法将 NULL 值插入 列“名称”,表 '设备制造商';列确实 不允许空值。插入失败。这 声明已终止。
此错误抱怨“名称”字段为空,但情况不应该如此。当我调试并单步执行此集合时,[“名称”] 具有我在表单上输入的值。
这是表创建语句。
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)); }
}
}
I am experiencing a very frustrating issue when trying to insert a new record
using LINQ to SQL. If I step through this code sometimes it inserts the new record
but most of the time it doesn't. When it fails I seeing the following error.
Cannot insert the value NULL into
column 'Name', table
'EquipmentManufacturer'; column does
not allow nulls. INSERT fails. The
statement has been terminated.
This error is complaining about the 'Name' field being null but that should not be the case. When I debug and step through this collection["Name"] has the value I entered on the form.
Here is the table create statement.
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]
Here is the ASP.NET MVC Controller and Create Action where I am trying to add a new record.
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();
}
}
}
Here is the Create.aspx view.
<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>
Here is the Repository implementation I am using.
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)); }
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
是因为您调用 .InsertOnSubmit(entity) 两次吗?
您在 New() 中调用一次
,然后在 .Insert() 中再次
调用它。我个人会从 New() 方法中删除 GetTable.InsertOnSubmit(entity) 。
原因是我认为存储库的用户最好专门插入实体,而不是每次创建新实体时自动设置为插入。
HTH,
查尔斯
Is it because you are calling .InsertOnSubmit(entity) twice?
You call it once in New()
And then again in .Insert()
Personally I would remove the GetTable.InsertOnSubmit(entity) from the New() method.
Reason being that I think it would be better for the user of the repository to specifically insert the entity rather than it automatically get set for insertion every single time they create a new one.
HTHs,
Charles
我遇到这个问题是因为我将 *.dbml Ling2SQL 文件中的
自动生成值
选项设置为true
;我将其更改为false
并且错误消失了。这是一个简单的错误,但我花了很长时间才发现,因为我没有故意将值设置为true
。I ran into this problem because I had set the
Auto Generated Value
option in my *.dbml Ling2SQL file totrue
; I changed it tofalse
and the error went away. Its a simple mistake but it took me forever to find as I didn't intentionally set the value totrue
.根据我的经验,此类问题通常来自映射配置中的错误。
寻找答案的一些建议:
使用 SQL Profiler 跟踪 INSERT 语句,这可能会给您更多线索。
仔细检查 EquipmentManufacturer 类的映射,名称可能未正确映射。在您的问题中包含该信息,因为它可以更好地描述问题。
In my experience this sort of problem generally comes from errors in the mapping configuration.
Some suggestions for finding an answer:
Use SQL Profiler to trace the INSERT statements, which might give you more clues.
Double-check the mapping for the EquipmentManufacturer class, Name might not be mapped correctly. Include that information in your question as it provides a better picture of the problem.
我发现您没有使用“自动绑定”(或者无论您如何称呼它,您接受想要绑定的实体作为操作方法参数),而是(A)更新对象并(B)设置其“手动从 formCollection 中获取“名称”属性。也许我没有看到“EquipmentManufacturerID”绑定在哪里?
此 EquipmentManufacturerID 属性是否为 NULL 失败?
I see that you are not using the 'auto-bind' (or whatever you call it, where you accept the entity you want bound as the action method parameter) but are instead (A) newing the object and (B) setting its "Name" property from the formCollection manually. Perhaps I do not see where the "EquipmentManufacturerID" is being bound?
Is the NULL failure on this EquipmentManufacturerID property?