Я хочу создать новую строку в своей базе данных в таблице, которая имеет несколько отношений внешнего ключа, и я не смог понять, в каком порядке и какие вызовы необходимо выполнить. Вот что у меня есть на данный момент:
db.Models.Order order = DB.Models.Order.CreateOrder( apple );
order.CustomerReference.Attach( ( from c in db.Customer where c.Id == custId select c ).First() );
db.SaveChanges();
Во второй строке код не работает, говоря:
Attach is not a valid operation when the source object associated with this related end is in an added, deleted, or detached state. Objects loaded using the NoTracking merge option are always detached.
Есть идеи?





(Спасибо, Джон, за исправления грамматики)
Вот и разобрался. Вот что вам нужно сделать:
db.Models.Order order = DB.Models.Order.CreateOrder( apple );
order.Customer = (from c in db.Customer where c.Id == custId select c).First();
db.SaveChanges();
Я надеюсь, что это поможет людям.
Почему бы не использовать ссылки на сущности? Ваш метод вызовет дополнительный оператор SELECT.
Намного удобнее использовать классы CustomerReference и EntityKey.
order.CustomerReference = new System.Data.Objects.DataClasses.EntityReference<Customers>();
order.CustomerReference.EntityKey = new EntityKey("ModelsEntities.Customers", "Id", custId);
Я согласен с kirkmcpherson, его способ избегает лишнего SELECT. Я думаю, вы цените поддерживаемый код выше производительности. Вы все еще можете использовать его способ, но вместо жестко закодированных строк вы можете использовать отражение для генерации строк, получая имена классов для ModelsEntities и Customers в приведенном выше примере. Таким образом вы получите на один SELECT меньше, и ошибки строгой типизации / компиляции. Добавленные накладные расходы из-за отражения не должны быть проблемой, ИМО.
Хорошо, вы можете использовать отражение для генерации имени набора сущностей, но не имени ключа (т.е. можно сгенерировать "ModelsEntities.Customers", используя строгую типизацию). Есть ли способ сгенерировать "Id" с помощью отражения?
Для обновления вот пример кода:
using (var ctx = new DataModelEntities())
{
var result = (from p in ctx.UserRole.Where(o => o.UserRoleId == userRole.UserRoleId)
select p).First();
result.RolesReference.EntityKey = new EntityKey("DataModelEntities.Roles",
"RoleId", userRole.RoleId);
result.UserRoleDescription = userRole.UserRoleDescription;
ctx.SaveChanges();
}
Я бы не возражал против использования вашего решения, но я хотел бы использовать строго типизированные имена столбцов базы данных, чтобы я мог получать ошибки времени компиляции, если связь недействительна.