Linq to SQL: почему я получаю ошибки IDENTITY_INSERT? - PullRequest
6 голосов
/ 12 марта 2009

Я использую Linq для SQL. У меня есть DataContext, против которого я .SubmitChanges () '. При вставке поля идентификации произошла ошибка:

Cannot insert explicit value for identity column in table 'Rigs' when IDENTITY_INSERT is set to OFF.

Единственное поле идентификатора - это «ID», значение которого равно 0. Оно определено в DBML как:

[Column(Storage="_ID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]

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

Почему я получаю эту ошибку?

Редактировать: вот запрос:

exec sp_executesql N'INSERT INTO [dbo].[Rigs]([id], [Name], [RAM], [Usage], [MoreInfo], [datetime], [UID])
VALUES (@p0, @p1, @p2, @p3, @p4, @p5, @p6)
SELECT [t0].[id], [t0].[OSID], [t0].[Monitors]
FROM [dbo].[Rigs] AS [t0]
WHERE [t0].[id] = @p7',N'@p0 int,@p1 varchar(1),@p2 int,@p3 varchar(1),@p4 varchar(1),@p5 datetime,@p6 int,@p7 
int',@p0=0,@p1='1',@p2=NULL,@p3='4',@p4='5',@p5=''2009-03-11 20:09:15:700'',@p6=1,@p7=0

Очевидно, что он проходит ноль, несмотря на то, что ему никогда не присваивалось значение.

Редактировать: Добавление кода:

Rig rig = new Rig();
int RigID;
try
{ // Confirmed these always contain a nonzero value or blank
    RigID = int.Parse(lbSystems.SelectedValue ?? hfRigID.Value);
    if (RigID > 0) rig = mo.utils.RigUtils.GetByID(RigID);
}
catch { }

rig.Name = Server.HtmlEncode(txtName.Text);
rig.OSID = int.Parse(ddlOS.SelectedValue);
rig.Monitors = int.Parse(txtMonitors.Text);
rig.Usage = Server.HtmlEncode(txtUsage.Text);
rig.MoreInfo = Server.HtmlEncode(txtMoreInfo.Text);
rig.RigsToVideoCards.Clear();
foreach (ListItem li in lbYourCards.Items)
{
    RigsToVideoCard r2vc = new RigsToVideoCard();
    r2vc.VCID = int.Parse(li.Value);
    rig.RigsToVideoCards.Add(r2vc);
}
rig.UID = c_UID > 0 ? c_UID : mo.utils.UserUtils.GetUserByToken(this.Master.LiveToken).ID;

if (!mo.utils.RigUtils.Save(rig))   
    throw new ApplicationException("There was an error saving your Rig. I have been notified.");
hfRigID.Value = rig.id.ToString();

public static User GetUserByToken(string token)
{
    DataClassesDataContext dc = new DataClassesDataContext(ConfigurationManager.ConnectionStrings["MultimonOnlineConnectionString"].ConnectionString);
return (from u in dc.Users
    where u.LiveToken == token
    select u).FirstOrDefault();
}

Кроме того, я замечаю, что когда я обновляю существующую установку (insertonsubmit), она не обновляется. Профилировщик даже не показывает ни одного запущенного запроса.

Ответы [ 7 ]

11 голосов
/ 30 апреля 2014

Моя теория о том, что произошло, выглядит следующим образом:

  1. Вы спроектировали и создали базу данных
  2. Вы создали контекст БД с помощью LINQ TO SQL в Visual Studio
  3. Вы забыли установить автоматическую идентификацию на вашем столе
  4. Вы исправили это, перейдя в свою базу данных и установив автоидентификацию
  5. Но вы забыли воссоздать / обновить контекст LINQ TO SQL DB !!!

: D

7 голосов
/ 12 марта 2009

Ваш код устанавливает значение идентификатора явно 0? (вместо того, чтобы оставить его нетронутым).

Обновление 1: Как вы указали в обновленной версии, linq2sql явно передает значение в БД. Вот тот, с которым у меня не было проблем:

[Column(Storage="_CustomerID", AutoSync=AutoSync.Always, DbType="Int NOT NULL IDENTITY", IsDbGenerated=true)]
public int CustomerID 

Я только что видел другой, и у него точно такое же определение того, которое вы используете.

[Column(Storage="_TestID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int TestID

Обновление 2: Что касается обновлений, вы не должны делать для этого InsertOnSubmit. Просто обновите значения и вызовите .SubmitChanges (должно быть исключение). На вставке это действительно странно, поскольку опубликованные вами атрибуты свойств кажутся правильными, поэтому метод Insert, генерируемый linq2sql, также должен быть корректным. Я попытался бы снова добавить таблицу в конструктор и проверить правильность всех свойств.

Обратите внимание, что сгенерированный метод вставки должен выглядеть следующим образом (с MatchRig_Insert):

private void InsertRig(Rig obj)
{
    System.Nullable<int> p1 = obj.Id;

this.Rig_Insert (/ * набор значений * /, ref p1); obj.Id = p1.GetValueOrDefault (); }

2 голосов
/ 17 ноября 2010

Убедитесь, что свойство Auto Generated Value в вашем dbml для этого столбца имеет значение true. Если нет, LINQ попытается установить значение по умолчанию в зависимости от типа.

1 голос
/ 12 марта 2009

похоже, что ваш идентификатор где-то назначен (даже если он по умолчанию равен 0) - не хотите ли вы опубликовать часть своего кода LINQ?

1 голос
/ 12 марта 2009

Если вы указываете значение столбца IDENTITY, вы должны добавить

SET IDENTITY_INSERT ON

перед вашими утверждениями SQL и

SET IDENTITY_INSERT OFF 

после того, как выключить его. Это касается ЛЮБОГО необработанного SQL. Если вы использовали LINQ для создания объекта, подобного:

var customer = new LinqContext.Customer;
customer.FirstName = "Bob";
customer.LastName = "Smith";

LinqContent.Customer.Add(customer);
LinqContext.SubmitChanges();

Я верю, что это сработает, прости меня, если у меня неправильные занятия. Вы получите основную идею.

Редактировать: Упс .. Извините, не прочитал весь вопрос, забираю его обратно, усталый и утомленный от работы ...

0 голосов
/ 05 октября 2016

В моем случае я забыл обновить свой dbml-файл после установки идентификатора столбца Id.

0 голосов
/ 12 марта 2015

У меня была точно такая же проблема.

Мое решение состояло в том, чтобы вручную превратить столбец идентификатора INT в обнуляемый INT? столбец в конструкторе DBML , конечно, не в самой таблице БД. Также установите DbType в NULL вместо NOT NULL. Вот так:

[Column(Storage="_TestID", AutoSync=AutoSync.OnInsert, DbType="Int NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)] 
public int? TestID

Это работает со всеми операциями с БД. При вставке просто установите для столбца идентификации значение NULL , а не 0.

...