Linq To SQL без явных отношений с внешним ключом - PullRequest
14 голосов
/ 06 марта 2009

Я работаю с несколькими устаревшими таблицами, которые имеют отношения, но эти отношения не были явно установлены как первичные / внешние ключи. Я создал файл .dbml с помощью «Linq To Sql Classes» и установил правильную связь Case.CaseID = CaseInfo.CaseID. Мой получившийся класс CasesDataContext.

Мои таблицы (один ко многим):

Case
------------------
CaseID (int not null)
MetaColumn1 (varchar)
MetaColumn2 (varchar)
MetaColumn3 (varchar)
...


CaseInfo
------------------
CaseInfoID (int)
CaseID (int nulls allowed)
CaseInfoMeta (varchar)
...

Я новичок в LinqToSQL и у меня проблемы с работой ..

CasesDataContext db = new CasesDataContext();
var Cases = from c in db.Cases
            where c.CaseInfo.CaseInfoMeta == "some value"
            select c;

(Правка) Моя проблема в том, что CaseInfo или CaseInfos недоступно как участник дел.

Я слышал от коллеги, что мог бы попробовать ADO.Net Entity Data Model для создания своего класса контекста данных, но еще не пробовал и хотел посмотреть, не потрачу ли я свое время или пойду другим путем , Любые советы, ссылки, помощь будут наиболее ценными.

Ответы [ 7 ]

26 голосов
/ 07 марта 2009

Вернитесь к конструктору и проверьте правильность установки отношения. Вот один пример из реальной жизни, когда BillStateMasters имеет свойство «CustomerMasters1» (клиенты для штата): alt text

Ps. очищается имя ...

Обновление 1: Также необходимо убедиться, что в обеих таблицах определен основной. Если первичный ключ не определен в базе данных (и не может быть определен по какой-либо причине), обязательно укажите его в конструкторе. Откройте свойства столбца и установите его в качестве первичного ключа. Тем не менее, отслеживание сущности также не будет работать, если у вас нет первичного ключа для сущности, что означает, что он удаляет молча, не обновляя сущность. Поэтому обязательно просмотрите все сущности и получите их все с первичным ключом (как я уже сказал, если он не может быть на БД, то на конструкторе).

5 голосов
/ 10 марта 2009
CasesDataContext db = new CasesDataContext();
var Cases = from c in db.Cases
            join ci in db.CaseInfo on
            ci.ID equals c.InfoID
            where ci.CaseInfoMeta == "some value"
            select new {CASE=c, INFO=ci};

мой "join" linq немного заржавел, но приведенное выше должно быть близко к тому, что вы хотите.

0 голосов
/ 10 марта 2009

После нескольких тестов я почти уверен, что отношения FK требуются в БД независимо от того, какие ассоциации созданы в Linq-to-SQL. то есть, если они не установлены явно в БД, то вам придется выполнить соединение вручную.

0 голосов
/ 06 марта 2009

Это с #? Я думаю, вам нужно == вместо = в этой строке:

where c.CaseInfo.CaseInfoMeta = "some value"

следует читать

where c.CaseInfo.CaseInfoMeta == "some value"
0 голосов
/ 06 марта 2009

Несколько вещей, которые вы можете попробовать:

Проверьте свойства ассоциации. Убедитесь, что свойство Parent было создано как Public. Он делает это по умолчанию, но что-то могло измениться.

Поскольку вы не получаете CaseInfo на C, попробуйте ввести его в другом направлении, чтобы увидеть, есть ли у вас ci.Case с intellisense.

Удалить и воссоздать ассоциацию все вместе.

Есть что-то очень простое, если что-то не так. Лучше всего удалить базу данных и воссоздать ее целиком.

Если ничего не помогает, переключитесь на NHibernate. :)

0 голосов
/ 06 марта 2009

Ваш запрос выглядит правильно и должен возвращать набор результатов запроса объектов Case.

Итак ... в чем проблема?

(Правка) Моя проблема в том, что CaseInfo недоступно в случаях ... то есть c.CaseInfo не существует там, где я при условии, что это было бы, если бы были явный первичный / внешний ключ отношения.

Что вы подразумеваете под "недоступно"? Если вы создали ассоциацию в конструкторе, как вы и сказали, тогда запрос должен сгенерировать SQL-код в соответствии с

SELECT [columns] 
FROM Case INNER JOIN CaseInfo 
   ON Case.CaseID = CaseInfo.CaseID
WHERE CaseInfo.CaseInfoMeta = 'some value'

Вы отладили ваш запрос linq, чтобы получить сгенерированный SQL? Что это возвращает?

0 голосов
/ 06 марта 2009

Установлена ​​ли связь «Один к одному» или «Один ко многим»? Если у вас установлена ​​связь «Один ко многим», то у вас есть EntitySet, а не EntityRef, и вам нужно будет использовать предложение where в зависимом наборе, чтобы получить правильное значение. Я подозреваю, что вы хотите отношения один-к-одному, что не по умолчанию. Попробуйте изменить его на One to One и посмотрите, сможете ли вы сконструировать запрос.

Примечание: я просто догадываюсь, потому что вы на самом деле не сказали нам, в чем на самом деле "проблема".

...