Linq2Sql - пытается обновить, но инструкция Set в sql пуста - PullRequest
6 голосов
/ 17 мая 2010

Это странно ... сделано множество обновлений раньше, но не могу понять, почему это не так. хотя я использую .net 4.0 сейчас - однако я сомневаюсь, что это ошибка в его реализации L2S. Это не так, как это странное и прекрасное применение этого. Хотя я вполне уверен, что этот код работал, когда я использовал RC.

Мне также удалось воспроизвести эту ошибку, построив проект с нуля, используя приведенную ниже информацию.

проблема здесь в том, что оператор обновления, сгенерированный L2S, не имеет полей в операторе set. Я попытался проверить, что pk установлен (единственная причина, по которой я думаю, что поле ervery будет обязательным в поле where), а также прочитать другие свойства dbml. Я использую linq2Sql около 1 года, и у меня никогда не было проблем ... Я все еще думаю, что у меня просто огромный пердит мозг.

Примечание: я убрал методы equals и GetHashCode, чтобы удалить некоторые поля - проблема не устраняется после этого. Я не очистил SQL, хотя.

У меня есть клиентский класс из базы данных. Я добавил метод с именем update

public partial class Client :  ICopyToMe<Client>

Метод CopyToMe унаследован от интерфейса

   public  interface ICopyToMe<T>
    {
        void CopyToMe(T theObject);
    }

также класс имеет переопределенный getHashCode

public override int GetHashCode()
{
    int retVal = 13 ^ ID ^ name.GetHashCode();
    return retVal;
}

и равно

public override bool Equals(object obj)
{
    bool retVal = false;
    Client c = obj as Client;
    if (c != null)
        if (c.ID == this.ID && c._name == this._name)
            retVal = true;
    return retVal;
} 

метод обновления в частичном классе

 public void UpdateSingle()
        {          
            L2SDataContext dc = new L2SDataContext();
            Client c = dc.Clients.Single<Client>(p => p.ID == this.ID);
            c.CopyToMe(this);
            c.updatedOn = DateTime.Now;

            dc.SubmitChanges();
            dc.Dispose();
                        }

Метод CopytoMe

 public void CopyToMe(Client theObject)
        {
            ID = theObject.ID;
            name = theObject.name;                
        }

Я беру клиента, который был выбран, меняя его имя и затем вызываю этот метод обновления. Сгенерированный sql выглядит следующим образом

exec sp_executesql N'UPDATE [dbo].[tblClient]
SET 
WHERE ([ID] = @p0) AND ([name] = @p1) AND ([insertedOn] = @p2) AND ([insertedBy] = @p3) AND ([updatedOn] = @p4) AND ([updatedBy] = @p5) 
AND ([deletedOn] IS NULL) AND ([deletedBy] IS NULL) AND (NOT ([deleted] = 1))',N'@p0 int,@p1 varchar(8000),@p2 datetime,@p3 int,@p4 
datetime,@p5 int',@p0=103,@p1='UnitTestClient',@p2=''2010-05-17 11:33:22:520'',@p3=3,@p4=''2010-05-17 11:33:22:520'',@p5=3

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

выбрать объект -> установить в поле новое значение -> отправить выбранный объект

шаблон много раз и не имел этой проблемы. в dbml также нет ничего явно плохого - хотя это, вероятно, ложное утверждение

есть идеи?

Эта проблема заставляет сидеть так, как будто мне придется вернуться к ADO.Net, что меня расстроило.

Ответы [ 2 ]

1 голос
/ 20 мая 2010

ОК, после некоторых обсуждений с очень полезными людьми из Microsoft я нашел ответ на эту проблему.

Linq использует хэш-код для индексации своих коллекций в хеш-таблице. Это означает, что функция хеш-кода должна работать только с полями, которые однозначно идентифицируют объект.

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

С другой стороны, метод Equals может проверять большее количество полей, т. Е. Его проверка более специфична, чем сравнение GetHashCode.

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

0 голосов
/ 17 мая 2010

Если этот точный оператор UPDATE отправляется в базу данных (без каких-либо аргументов SET), то вы обнаружили ошибку в LINQ to SQL. Попробуйте свой код в .NET 4.0 и, если он все еще не работает, отправьте сообщение об ошибке на сайт Microsoft Connect.

...