2008-10-26 5 views
5

Я пытаюсь использовать LINQ, чтобы вставить запись в дочернюю таблицу, а я - , получив ошибку «Указанный приведение недействителен», которая имеет что-то делать w/ связанные ключи. Трассировка стека:LINQ to SQL -

Сообщение: Указанный приказ недействителен.

Тип: System.InvalidCastException Источник: System.Data.Linq TargetSite: булевы TryCreateKeyFromValues ​​(System.Object [], V ByRef) HelpLink: нуль Стек: в System.Data.Linq.IdentityManager.StandardIdentityManager .SingleKeyManager 2.TryCreateKeyFromValues(Object[] values, V& v) at System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache 2.Find (Object [] KeyValues) при System.Data.Linq.IdentityManager.StandardIdentityManager.Find (метатип типа, Object [] KeyValues) при System.Data.Linq.CommonDataServices.GetCachedObject (метатип type, Object [] keyValues) в System.Data.Linq.ChangeProcessor.GetOtherItem (MetaAsso рирует ассоциативный, объект экземпляра) при System.Data.Linq.ChangeProcessor.BuildEdgeMaps() на System.Data.Linq.ChangeProcessor.SubmitChanges (ConflictMode failureMode) на System.Data.Linq.DataContext.SubmitChanges (ConflictMode failureMode) в System.Data.Linq.DataContext.SubmitChanges()

(.....)

Эта ошибка быть брошенными на следующий код:

ResponseDataContext db = new ResponseDataContext(m_ConnectionString); 
CodebookVersion codebookVersion = db.CodebookVersions.Single(cv => cv.VersionTag == m_CodebookVersionTag); 
ResponseCode rc = new ResponseCode() 
    { 
     SurveyQuestionName = "Q11", 
     Code = 3, 
     Description = "Yet another code" 
    }; 
codebookVersion.ResponseCodes.Add(rc); 
db.SubmitChanges(); //exception gets thrown here 

Эти таблицы имеют отношения FK между двумя из них.
Столбец родительской таблицы называется «id», является PK и имеет тип: INT NOT NULL IDENTITY
Столбец дочерней таблицы называется «responseCodeTableId» и имеет тип: INT NOT NULL.

codebookVersion (родительский класс) карты для таблицы tblResponseCodeTable
responseCode (ChildClass) сопоставлена ​​таблицы tblResponseCode

Если я выполнить SQL непосредственно, она работает. например

INSERT INTO tblResponseCode 
(responseCodeTableId, surveyQuestionName, code, description) 
VALUES (13683, 'Q11', 3, 'Yet another code') 

Обновления к тому же классу работают нормально. например

codebookVersion.ResponseCodes[0].Description = "BlahBlahBlah"; 
db.SubmitChanges(); //no exception - change is committed to db 

Я рассмотрел переменную, RC, после операции .Add() и это, действительно, получить надлежащее responseCodeTableId, так же, как я бы ожидать, так как я добавляю его в этой коллекции.

tblResponseCodeTable's full definition: 
COLUMN_NAME TYPE_NAME 
id     int identity 
responseCodeTableId int 
surveyQuestionName nvarchar 
code    smallint 
description   nvarchar 
dtCreate   smalldatetime 

dtCreate имеет значение по умолчанию GetDate().

Единственный бит полезной информации, которую я могу думать о том, что ни SQL не когда-нибудь пробовали с базой данных, поэтому LINQ взрывает прежде, чем она попыток (отсюда и ошибка не будучи SqlException). Я профилировал и проверял , что не предпринимаются попытки выполнить какие-либо инструкции в базе данных.

Я читал и видел проблему, когда у вас есть отношение к полю не ПК, но это не соответствует моему делу.

Может ли кто-нибудь пролить свет на эту ситуацию для меня? Какая невероятно очевидная вещь мне не хватает здесь?

Большое спасибо.
Пол Prewett

+0

Аналогичная проблема обсуждается здесь, решены мои проблемы: http://stackoverflow.com/questions/4801364/specified-cast-is-not-valid-error-when-saving- linq-to-sql-entity –

ответ

0
ResponseCode rc = new ResponseCode() 
    { 
     SurveyQuestionName = "Q11", 
     Code = 3, 
     Description = "Yet another code" 
    }; 

и:

INSERT INTO tblResponseCode 
(responseCodeTableId, surveyQuestionName, code, description) 
VALUES (13683, 'Q11', 3, 'Yet another code') 

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

Просто некоторые идеи.

+0

rc добавляется через свойство FK кодовой книгиVersion -> codebookVersion.ResponseCodes.Add (rc); – chakrit

0

Этот блок:

codebookVersion.ResponseCodes.Add(rc); 
db.SubmitChanges(); //exception gets thrown here 

Вы можете попробовать InsertOnSubmit вместо Add? т.е.

codebookVersion.ResponseCodes.InsertOnSubmit(rc); 

Я думаю Add не предназначен для использования для вставки записи, если моя память мне. InsertOnSubmit - тот, который нужно использовать.

0

Чтобы сузить виновника.

Вы пытались заменить анонимный словарь с чем-то вроде:

ResponseCode rc = new ResponseCode(); 

rc.SurveyQuestName = "Q11"; 
rc.Code = 3; 
rc.Description = "Yet Another Code"; 

Я еще реально работать с .NET 3.5 еще (день работа по-прежнему все 2,0), так что если мне интересно там это проблема с передачей данных с использованием анонимного словаря (случаи не соответствуют столбцам SQL для одного).

1

Опубликовать схему родительской таблицы.

Если вы посмотрите здесь, некоторые другие люди столкнулись с вашей проблемой. http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=3493504&SiteID=1

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

0

Да, я прочитал это и другие сообщения, но всегда кажется, что кто-то связан с полем, которое просто имеет уникальный контраст. Или в случае этого парня (который звучит точно так же, как у меня), он не получил решения.

Вот родительская таблица:

tblResponseTable definition (which maps to CodebookVersion) 
COLUMN_NAME TYPE_NAME 
id int identity 
versionTag nvarchar 
responseVersionTag nvarchar 

versionTag имеет уникальный contraint на нем, но это не представляется везде, где я могу увидеть в материале LINQ-to-SQL - и так ничего и не идет к база данных ... все еще застряла.

1

Поскольку база данных не называется, я думаю, вам нужно посмотреть на сопоставления linq на sql. Как выглядит Ассоциация? Должна быть Ассоциация как для родительского, так и для дочернего классов. Ознакомьтесь с интерфейсом linq to sql между двумя классами. У Ассоциации должно быть свойство ThisKey. Я думаю, что приведение, которое терпит неудачу, пытается отличить значение свойства, на которое указывает этот ключ. Насколько я могу судить, может возникнуть проблема, когда имеется более одного ключа, а тип первого ключа не соответствует типу, который указывает этот ключ. Я не уверен, как linq определит, что такое первый ключ. По внешнему виду у вас есть только один ключ и один внешний ключ, поэтому это не должно быть проблемой, но дизайнер, если вы его используете, как известно, становится творческим. Я довольно много догадываюсь, но это похоже на то, что я видел раньше.

0

Майк, я вас слышу. Но независимо от того, где я смотрю, все выглядит правильно. Я проверил и перепроверял, что ResponseTableId является int и этот Id является int. Они определены как таковые в дизайнере, и когда я смотрю на сгенерированный код, все снова выглядит в порядке.

Я изучил ассоциации. Вот они:

[Table(Name="dbo.tblResponseCode")] 
public partial class ResponseCode : ... 
    ... 
    [Association(Name="CodebookVersion_tblResponseCode", Storage="_CodebookVersion", ThisKey="ResponseCodeTableId", OtherKey="Id", IsForeignKey=true)] 
    public CodebookVersion CodebookVersion 
    { 
     ... 
    } 

[Table(Name="dbo.tblResponseCodeTable")] 
    public partial class CodebookVersion : ... 
    ... 
    [Association(Name="CodebookVersion_tblResponseCode", Storage="_ResponseCodes", ThisKey="Id", OtherKey="ResponseCodeTableId")] 
    public EntitySet<ResponseCode> ResponseCodes 
    { 
     ... 
    } 

И скриншот ассоциации в случае, поможет:
designer

Любые дальнейшие мысли?

0
ResponseCode rc = new ResponseCode() 
{ 
    CodebookVersion = codebookVersion, 
    SurveyQuestionName = "Q11", 
    Code = 3, 
    Description = "Yet another code" 
}; 
db.ResponseCodes.InsertOnSubmit(rc); 
db.SubmitChanges(); 
0

Вы можете проверить, чтобы увидеть, что все поля в таблицы базы данных, которые устанавливаются сервером БД при вставке новой записи есть, что отражено в диаграмме Linq к SQL. Если вы выберете поле на диаграмме Linq to SQL и просмотрите его свойства, вы увидите поле «Auto Generated Value», которое, если установлено значение true, гарантирует, что все новые записи будут иметь значение по умолчанию, указанное в базе данных.

0
+0

Спасибо за downvote. Вы заметите, что этому ответу 3 года, и это был разговор в то время. –

+0

Я проигнорировал по двум причинам: 1) Он вообще не затрагивает проблему, описанную в OP (я недавно столкнулся с этой проблемой); и 2) специально связанное сообщение в блоге не упоминает об устаревании в нем, а наоборот говорит: «Мы слушаем клиентов относительно LINQ to SQL и будем продолжать развивать продукт на основе отзывов, которые мы также получаем от сообщества». – DuckMaestro

+1

Достаточно честный. Спасибо за объяснение. –

0

У меня возникла очень похожая проблема. Я свяжусь вас к моему словесному посту: http://forums.asp.net/p/1223080/2763049.aspx

И я также предложить решение, только предположение ...

ResponseDataContext db = new ResponseDataContext(m_ConnectionString); 
    CodebookVersion codebookVersion = db.CodebookVersions.Single(cv => cv.VersionTag == m_CodebookVersionTag); 
    ResponseCode rc = new ResponseCode() 
    { 
     ResponseCodeTableId = codebookVersion.Id, 
     SurveyQuestionName = "Q11", 
     Code = 3, 
     Description = "Yet another code" 
    }; 
    db.ResponseCodes.InsertOnSubmit(rc); 
    db.SubmitChanges(); 
0

Где-то в вашем графике объекта есть ошибка преобразования, базовая модель данных (или модель Linq To SQL) изменилась. Обычно это что-то вроде NVARCHAR (1) -> CHAR, когда это должно быть STRING или что-то подобное.

Эта ошибка не является забавой для поиска, надеюсь, ваша объектная модель невелика.

1

Это пример этого bug? Если это так, попробуйте запустить свой код в .NET 4.0 сейчас, когда бета-версия отсутствует.

Если, как и я, вы не готовы начать использовать бета-версию, вы можете решить эту проблему. Похоже, что проблема заключается в том, что LINQ не поддерживает отношения, определенные для непервичных ключевых полей. Однако термин «первичный ключ» не относится к первичному ключу, определенному в таблице SQL, а первичному ключу, определенному в дизайнере LINQ.

Если вы перетащили свои таблицы в конструктор, Visual Studio автоматически проверит первичный ключ, определенный в базе данных, и пометит соответствующее поле класса как «первичные ключи». Однако они не должны соответствовать друг другу. Вы можете удалить выбранный вами ключ Visual Studio и выбрать другое поле (или группу полей).Конечно, вам нужно убедиться, что это логично (у вас должно быть уникальное ограничение в базе данных в выбранном поле/поля).

Итак, у меня было 2 таблицы/классы, связанные с eachother, используя альтернативный ключ. В родительской таблице было 2 ключа: суррогатный первичный ключ, определенный как int, и альтернативный естественный ключ, определяемый как строка. В конструкторе LINQ я определил ассоциацию с использованием альтернативного ключа, и я испытал InvalidCastException при попытке обновить это поле ассоциации на дочернем объекте. Чтобы обойти это, я вошел в конструктор LINQ, выбрал int, а затем изменил свойство основного ключа с True на False. Затем я выбрал строку и установил для нее свойство Primary Key значение True. Перекомпилирован, повторно протестирован и исключение InvalidCastException.

Глядя на ваш скриншоте это выглядит, как вы можете быть в состоянии устранить проблему путем изменения первичного ключа LINQ на ResponseCode от ResponseCode.ID к ResponseCode.ResponseCodeTableID