У меня есть отношение родитель-потомок между двумя таблицами с именами: Relation и Resource, так что Relation.RESOURCE_ID == Resource.ID
Если я запишу свою ассоциацию в файл dbml, так что Отношение -> Ресурс на RESOURCE_ID = ID, я не смогу добавить Ресурс к объекту Отношения. Мощность ассоциации один к одному.
tbl_res_Resource resoure = new tbl_res_Resource()
{
//ID is auto calculated
RESOURCE_KEY = "some key",
RESOURCE_TYPE = 20,
};
tbl_res_Relation relation = new tbl_res_Relation()
{
ENTITY_ID = 10,
ENTITY_TYPE_ID = 10,
//ID is auto calculated
//RESOURCE_ID should be inferred
};
relation.Resource = resoure;
context.tbl_res_Relations.InsertOnSubmit(relation);
context.SubmitChanges();
Отправить изменения
System.Data.Linq.ForeignKeyReferenceAlreadyHasValueExceptio с сообщением «Недопустимая операция из-за текущего состояния объекта».
Но если я перейду к модели (dbml) и изменю ассоциацию (так что Resource -> Relation on ID == RESOURCE_ID), тогда все будет работать нормально... без изменения строки кода.
Имейте в виду, что все ассоциации определяются только на уровне dbml, в базе данных нет внешнего ключа.
Что мне здесь не хватает?





Что мне здесь не хватает?
Ничего, это правильно. Неважно, что кардинальность один к одному. Ассоциация в LINQ2SQL — это абстракция на уровне приложения, эквивалентная определению внешнего ключа на уровне базы данных. И LINQ2SQL ожидает, что вы будете следовать ограничениям этой ассоциации точно так же, как вы должны были бы следовать ограничениям эквивалентного внешнего ключа на уровне базы данных.
чего я не понимаю, так это почему изменение ассоциации 1-1 (в модели dbml) приведет к разрыву ассоциации. Это один к одному, у него нет ни предпочтительного направления, ни ограничений на уровне БД.
Опять же, это не имеет ничего общего с кардинальностью (один к одному), и ассоциации всегда имеют направление (от родителя к дочернему (детям)) в зависимости от того, как вы их настроили. Если вы посмотрите в окно свойств ассоциации, вы увидите, что там указано, какой объект является родительским, а какой дочерним.
В своем коде вы устанавливаете поле relation.Resource для объекта resource, поэтому говорите, что resource является родителем, а relation — дочерним:
relation.Resource = resoure;
Вышеприведенное эквивалентно созданию на уровне базы данных relation дочерней таблицы с внешним ключом, определенным в Resource поле, относящемся к родительской resource таблице.
Если ваша ассоциация определена таким образом, что relation является родителем, то приведенный выше код не соответствует ограничению, потому что у вас есть дочерний объект resource, которому вы не назначаете родителя. Вам понадобится что-то вроде следующего, чтобы придерживаться ограничения:
resource.Relation = relation;
@Skary Пожалуйста, смотрите мой обновленный ответ. Я думаю, что часть, на которой вы спотыкаетесь, заключается в том, что вы не понимаете, что ассоциации всегда имеют направление, и это важно (поскольку это направление определяет направление реляционного ограничения на прикладном уровне).
Итак, в основном мне нужно назначить родителя ребенку и никогда иначе? Если это то, как работает Linq To SQL, то я понимаю, что меня смущает. Я ожидаю, что я также могу назначить дочерний элемент родителю, и это то же самое (я имею в виду, что я пытаюсь сделать это, дважды изменив dbml, по крайней мере, в одном случае должно быть правильно). Потому что здесь люди действуют точно так же, как я, назначая деталь (дочернюю) и заказ (родительскую), а не наоборот: stackoverflow.com/questions/4356988/… Почему я не могу этого сделать?
Извините за двойной комментарий, но я хотел бы внести ясность, я знаю, что в DBML есть направление, и я только что попытался снова его переключить. Но кажется, что в любом случае я должен назначить родителя дочернему элементу, но в связанном примере (и из того, что я помню) должна быть возможность назначить дочерний элемент родителю. Мне все равно, какое направление я должен выбрать в DBML (нет предпочтительного «логически»), я нашел более «правильным» и читаемым, чтобы назначить ребенка родителю, а не наоборот (это моя цель).
@Skary Да, синтаксически это может показаться нелогичным, но ваш экземпляр вашего дочернего объекта имеет свойство для родителя (точно так же, как в базе данных дочерняя таблица будет иметь столбец для поля внешнего ключа, который относится к родительской таблице) . Вам нужно установить это свойство для дочернего объекта (так же, как в базе данных вам потребуется заполнить этот столбец внешнего ключа). Так что да, когда у вас есть ассоциация, определенная между двумя объектами, если вы создаете экземпляр дочернего объекта, ассоциация имеет ограничение, которое заставляет вас устанавливать родительское свойство этого дочернего объекта.
Да, это ясно для меня, но я не понимаю, почему изменение ассоциации 1-1 (в модели dbml) нарушит ассоциацию. Это один к одному, у него нет ни предпочтительного направления, ни ограничений на уровне БД. Итак, если это работает в одном конкретном направлении (от ребенка к родителю), почему не работает в противоположном (при правильном моделировании)? Потому что очень сложно понять, что ребенок смоделирован как родитель, просто чтобы ассоциация работала, как задумано.