Сбой LINQ to SQL INSERT - PullRequest
       11

Сбой LINQ to SQL INSERT

4 голосов
/ 26 августа 2009

У меня очень неприятная проблема при попытке вставить новую запись используя LINQ to SQL. Если я перебираю этот код, иногда он вставляет новую запись но в большинстве случаев это не так. Когда это не удается, я вижу следующую ошибку.

Невозможно вставить значение NULL в столбец «Имя», таблица 'EquipmentManufacturer'; колонка делает не разрешать нули. Вставить не удается. заявление было прекращено.

Эта ошибка жалуется на то, что поле 'Имя' имеет значение 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 Controller и Create Action, где я пытаюсь добавить новую запись.

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 ]

3 голосов
/ 26 августа 2009

Это потому, что вы дважды вызываете .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);
}

Лично я бы удалил GetTable.InsertOnSubmit (entity) из метода New ().

Причина в том, что я думаю, что было бы лучше, если бы пользователь хранилища специально вставлял сущность, а не автоматически устанавливал ее для вставки каждый раз, когда он создает новую.

HTHS,
Charles

1 голос
/ 26 декабря 2011

Я столкнулся с этой проблемой, потому что я установил параметр Auto Generated Value в моем файле * .dbml Ling2SQL на true; Я изменил его на false, и ошибка исчезла. Это простая ошибка, но мне потребовалось целую вечность, чтобы найти ее, поскольку я специально не установил значение true.

0 голосов
/ 26 августа 2009

Я вижу, что вы не используете 'auto-bind' (или как вы его называете, где вы принимаете сущность, которую вы хотите связать в качестве параметра метода действия), но вместо этого (A) обновляете объект и (B) установив его свойство «Имя» из formCollection вручную. Возможно, я не вижу, где привязан «EquipmentManufacturerID»?

Ошибка NULL в этом свойстве EquipmentManufacturerID?

0 голосов
/ 26 августа 2009

По моему опыту, проблема такого рода обычно возникает из-за ошибок в конфигурации сопоставления.

Некоторые предложения по поиску ответа:

  • Используйте SQL Profiler для отслеживания операторов INSERT, которые могут дать вам больше подсказок.

  • Дважды проверьте сопоставление для класса EquipmentManufacturer, имя может отображаться неправильно. Включите эту информацию в свой вопрос, поскольку она дает более полное представление о проблеме.

...