LINQ to SQLを使用して新しいレコード を挿入しようとすると、非常に不満な問題が発生します。このコードをステップ実行すると、新しいレコード が挿入されることがありますが、ほとんどの場合は挿入されません。失敗すると、次のエラーが表示されます。LINQ to SQL INSERTに失敗する
コラム '名前'、表 にNULL値を挿入することはできません 'EquipmentManufacturer';列は はnullを許可しません。 INSERTは失敗します。 ステートメントが終了しました。
このエラーは、「名前」フィールドがnullであると不平を言っていますが、そうではありません。このコレクション["Name"]をデバッグしてステップ実行すると、フォームに入力した値があります。
ここにtable 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>
私が使用しているリポジトリの実装は次のとおりです。
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)); }
}
}
これは私の問題を解決するようですが、私はなぜそれほど確かではありません。私がリポジトリのNewメソッドからGetTable.InsertOnSubmit(エンティティ)をコメントアウトすると、それは機能します。リポジトリの新規メソッドでInsertOnSubmitコールを残し、コントローラでreposManu.Insert(エンティティ)コールをコメントアウトすると失敗します。 – MHinton
ちょうど言ったことで判断すると、.InsertOnSubmit(エンティティ)を呼び出すときにオブジェクトを保存するためにオブジェクトのコピーが必要になります。したがって、新しいEquipmentManufacturerというブランドのブランドでInSertOnSubmitを呼び出すと、値を含まないコピーを挿入しようとします。そのため、データベースの制約に失敗します。 – Charlino
ありがとうございました。 – MHinton