Linq To SQL без явных отношений внешнего ключа
-
03-07-2019 - |
Вопрос
Я работаю с несколькими устаревшими таблицами, у которых есть связи, но эти связи не были явно установлены как первичные/внешние ключи.Я создал файл .dbml, используя «Классы Linq To Sql», и установил правильную ассоциацию 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 для создания своего класса контекста данных, но еще не пробовал этого и хотел посмотреть, буду ли я тратить свое время или мне следует пойти другим путем.Любые советы, ссылки, помощь будут очень признательны.
Решение
Вернитесь к дизайнеру и проверьте, что связь настроена правильно.Вот один пример из реальной жизни: BillStateMasters имеет свойство «CustomerMasters1» (клиенты для штата):
Пс.именование подчищается...
Обновление 1: Вам также необходимо убедиться, что в обеих таблицах определена первичная таблица.Если первичный ключ не определен в базе данных (и не может быть определен по какой-либо причине), обязательно определите его в конструкторе.Откройте свойства столбца и установите его в качестве первичного ключа.Тем не менее, отслеживание объекта также не будет работать, если у вас нет первичного ключа для объекта, что в случае удаления означает, что объект не обновляется автоматически.Итак, обязательно просмотрите все объекты и убедитесь, что у них всех есть первичный ключ (как я уже сказал, если он не может быть в базе данных, то в дизайнере).
Другие советы
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};
мой " присоединиться " linq немного заржавел, но вышесказанное должно приблизиться к тому, что вы хотите.
Установлена ли связь «Один к одному» или «Один ко многим»?Если у вас установлена связь «Один ко многим», то у вас есть EntitySet, а не EntityRef, и вам нужно будет использовать предложениеwhere в зависимом наборе, чтобы получить правильное значение.Я подозреваю, что вам нужны отношения «Один к одному», которые не используются по умолчанию.Попробуйте изменить его на «Один к одному» и посмотрите, сможете ли вы построить запрос.
Примечание:Я просто предполагаю, потому что вы на самом деле не рассказали нам, в чем на самом деле «проблема».
Ваш запрос выглядит правильно и должен возвращать набор результатов запроса объектов Case. Р>
Итак ... в чем проблема?
(Правка) Моя проблема в том, что CaseInfo недоступно в случаях ... то есть c.CaseInfo не существует там, где я при условии, что это было бы, если бы были явный первичный / внешний ключ отношения.
Что вы подразумеваете под "недоступно"? Если вы создали ассоциацию в конструкторе, как вы сказали, тогда запрос должен сгенерировать SQL-код в соответствии с
SELECT [columns]
FROM Case INNER JOIN CaseInfo
ON Case.CaseID = CaseInfo.CaseID
WHERE CaseInfo.CaseInfoMeta = 'some value'
Вы уже отладили свой запрос linq, чтобы получить сгенерированный SQL? Что это возвращает?
Несколько вещей, которые вы можете попробовать:
Проверьте свойства ассоциации. Убедитесь, что свойство Parent было создано как Public. Он делает это по умолчанию, но что-то могло измениться.
Поскольку вы не получаете CaseInfo на C, попробуйте ввести его в другом направлении, чтобы узнать, есть ли у вас ci.Case с intellisense.
Удалите и воссоздайте ассоциацию все вместе.
Есть что-то очень плохое, если дочерние элементы не появляются. Лучше всего удалить dbml и воссоздать все это.
Если ничего не помогает, переключитесь на NHibernate. :) Р>
После нескольких тестов я почти уверен, что отношения FK требуются в БД независимо от того, какие ассоциации созданы в Linq-to-SQL. то есть, если они не установлены явно в БД, то вам придется выполнить соединение вручную.
Это с #? Я думаю, вам нужно ==
вместо = в этой строке:
where c.CaseInfo.CaseInfoMeta = "some value"
следует прочитать
where c.CaseInfo.CaseInfoMeta == "some value"