Entity Framework-вставка записей в дочернюю таблицу, когда родительская запись уже существует
Добрый день-
Я разрабатываю приложение Silverlight с использованием LINQ to Entity Framework для уровня доступа к данным. Моя N-уровневая модель базы данных включает около 30 таблиц с несколькими многоуровневыми отношениями родитель-потомок. Недавно начал писать мои службы данных и модульные тесты и обнаружил проблему с вставкой новой записи в дочернюю таблицу, когда запись родительской таблицы уже определена. Вот сокращенная версия моего родительские и дочерние таблицы:
РОДИТЕЛЬСКАЯ ТАБЛИЦА:
пользователи
UserID (PK)
Электронная почта
Пароль
так далее...
ДОЧЕРНЯЯ ТАБЛИЦА:
пользовательских профилей
UserProfileID (PK)
Различные данные профиля...
UserID (FK -- таблица пользователей)
Итак, на данный момент у меня есть Entity Framework, который уже использовался для создания мои различные классы для ORM, и я ищу, чтобы создать службы данных для операций CRUD на моих сущностях. Ниже приведен пример кода для моего метода для вставки нового пользователей (который не имеет ссылок на родительскую таблицу):
public User CreateUser(User newUser)
{
using (var _context = new ProjectDatabase())
{
newUser.CreatedDate = DateTime.Now;
newUser.ModifiedDate = DateTime.Now;
_context.AddToUsers(newUser);
_context.SaveChanges();
}
return newUser;
}
это работает просто отлично. Я написал модульные тесты для него, без проблем. Теперь, с другой стороны, рассмотрим следующий метод службы данных, который я написал, чтобы вставить новый UserProfile объект в базу данных. Начать с, у меня есть очень похожий сервис данных:
public UserProfile CreateProfile(UserProfile newUserProfile)
{
using (var _context = new ProjectDatabase())
{
newUserProfile.CreatedDate = DateTime.Now;
newUserProfile.ModifiedDate = DateTime.Now;
_context.AddToUserProfiles(newUserProfile);
_context.SaveChanges();
}
return newUserProfile;
}
этот код, как и другой, компилируется без проблем. Однако мой модульный тест постоянно терпит неудачу. Вот код для моего модульного теста:
[TestMethod]
public void UserProfileCrudTest()
{
IProfileDataService _dataService = new ProfileDataService();
// Pre-seeded data on a State for foreign key
State _myState;
using (var _context = new ProjectDatabase())
{
_myState = _context.States.First();
}
// Creating temporary User for association with new UserProfile
User _myUser = new User()
{
Email = "test",
Password = "test",
IsActive = true,
NameFirst = "test",
NameLast = "test"
};
_myUser = _dataService.CreateUser(_myUser);
Assert.IsNotNull(_myUser);
// Attempt to create new UserProfile, assigning foreign key
_myUserProfile = new UserProfile()
{
Address = "123 Main",
City = "Anywhere",
State = _myState,
PostalCode = "63021",
UserID = _myUser.UserID
};
// This call to CreateProfile throws an exception and the test fails!!
_myUserProfile = _dataService.CreateProfile(_myUserProfile);
Assert.IsNotNull(_myUserProfile);
// Remaining test code... never gets this far...
}
Итак, на данный момент мой модульный тест выдает следующее исключение:
метод тестирования MyProject.Служб dataservices.Тесты.SecurityTests.UserProfileCrudTest выбросил исключение:
1 ответов
вам не нужно делать все эти вещи. С EF 4.0 ваш код может быть таким простым:
public UserProfile Create(UserProfile userProfile) {
using (var context = new ProjectDatabase()) {
//add the new graph to the context:
context.UserProfiles.AddObject(userProfile);
context.SaveChanges();
}
return userProfile;
}
public void UserProfileCrudTest() {
User _myUser = new User() {
Email = "test",
...
};
UserProfile _myUserProfile = new UserProfile() {
Address = "123 Main",
...
};
// join the new UserProfile to the User
_myUserProfile.User = _myUser;
UserProfile userProfile = Create(_myUserProfile);
}
объяснение:
то, что вы сделали, имеет смысл в типичных сценариях доступа к данным, где вам придется сначала вставить новый пользователей, вернуть UserID, а затем использовать это, чтобы вставить новый UserProfile. Однако,SaveChanges делает все это для вас, когда он видит, что оба
новые и что они связаны. Он также использует сопоставления модели, чтобы выяснить, какие
является зависимой сущностью (в данном случае UserProfile) и нуждается во внешнем ключе (UserID).
С этой информацией он выполняет вставки базы данных в правильном порядке.
добавление нового UserProfile к существующему пользователю:
Если вы хотите добавить новый UserProfile к существующему пользователю, и у вас уже есть объект пользователя, к которому вы хотите добавить профиль, вы можете просто связать их пишу:
userProfile.User = yourUserObject
// OR
yourUserObject.UserProfiles.add(userProfile)
а затем вызовите SavingChanges ().
Если у вас есть только UserID, вы можете установить его так же, как UserProfile.UserID = идентификатор пользователя. Кстати, я знаю, что это то, что вы изначально пытались сделать, и у вас есть исключение, поэтому вот что вам нужно сделать:
1. Обновите модель из базы данных, чтобы убедиться, что она полностью синхронизирована с БД.
2. Шаг через код и убедитесь, что вы устанавливаете законный UserID для объекта UserProfile (что - то, что действительно существует в пользовательской таблице) - вы даже можете попытаться жестко его закодировать.
3. Запустите его снова, и если вы все еще получаете исключение, пожалуйста, опубликуйте трассировку стека, так как я запустил ваш код, и я не получил его, поэтому ваше исключение может исходить из совершенно другой проблемы.