LINQ to SQL 1: 1 Вставка - PullRequest
       15

LINQ to SQL 1: 1 Вставка

1 голос
/ 15 сентября 2011

Я сейчас сталкиваюсь с этой проблемой. Я вручную сопоставил POCO с таблицами базы данных через LINQ to SQL. Я хочу поместить все эти объекты / таблицы в один контекст (рассматриваемый как транзакция), чтобы в случае сбоя в транзакции все откатывалось.

Теперь проблема, с которой я сталкиваюсь, заключается в том, что у меня есть UserLogin и UserProfile (соотношение 1: 0 - 1). Они структурированы таким образом, что идентификатор UserLogin представляет собой PK и FK для UserProfile, и то же самое относится к UserProfile. На UserLogin это установлено, чтобы автоматически генерировать идентичность с IsDBGenerated, установленным в true. UserProfile, с другой стороны, не имеет IsDBGenerated.

UserProfile устанавливается как EntityRef в UserLogin, и, поскольку они происходят из одного контекста, я устанавливаю UserLogin.UserProfile = new UserProfile () при создании.

После назначения всех свойств я сделал table.InsertOnSubmit (UserLogin) и context.SaveChanges ().

Здесь и возникает настоящая проблема. Идентификатор UserProfile остается равным 0.

Может кто-нибудь помочь?


Извините, я не прояснил себя. Используемый SQL Server - это MS SQL Server 2008.

Структура сущности такая,

UserLogin является обязательным при регистрации, в то время как UserProfile - нет, что делает соотношение 1: 0 - 1. Поэтому было бы неразумно использовать автоинкремент для обеих таблиц.

PK UserProfile также является FK, который ссылается на UserLogin.

@ GertArnold, да, я установил идентификатор UserProfile = идентификатор UserLogin в коде позади asp.net, но перед сохранением контекста идентификатор UserLogin останется равным 0, так как в этот момент я хочу, чтобы обе записи были добавлены вместе, и мне было интересно если бы у Linq to Sql был какой-то способ решить это. Поскольку я добавил атрибут Association, по праву Linq в Sql должен распознать эту зависимость и добавить идентификатор при отправке, или, по крайней мере, это мое желаемое за действительное.

В моем профиле пользователя у меня есть этот фрагмент:

[Column(IsPrimaryKey = true)]
public long id { get; set; }
private EntityRef<UserLogin> _login;
[Association(ThisKey = "id", Storage = "_login")]
public UserLogin UserLogin { get { return _login.Entity; } 
    set { _login.Entity = value; } }

В моем UserLogin у меня есть следующий фрагмент:

[Column(IsPrimaryKey = true, IsDbGenerated = true, AutoSync = AutoSync.OnInsert)]
public long id { get; set; }
private EntityRef<UserProfile> _profile;
[Association(ThisKey = "id", Storage = "_profile")]
public UserProfile UserProfile { get { return _profile.Entity; } 
    set { _profile.Entity = value; } }

Наконец, в моем коде есть следующее:

UserLogin login = new UserLogin();
// All assigning here
login.UserProfile = new UserProfile();
// Assign here
login.userProfile.id = login.id;

На данный момент оба идентификатора равны нулю, поскольку ни один из них еще не вставлен.

Когда я делаю context.SubmitChanges (), идентификатор UserLogin получит увеличенное значение, но идентификатор UserProfile останется равным 0. Причина, по которой я хочу обернуть оба в одном и том же контексте и отправить вместе, состоит в том, чтобы избежать случаев, таких как, скажем, UserLogin передан , но UserProfile обнаруживает ошибку. Так что в моей БД есть запись для входа в систему, но не для профиля, которая портит мои данные.

1 Ответ

2 голосов
/ 19 сентября 2011

Мне приходилось читать этот вопрос несколько раз, чтобы понять, к чему вы клоните.Эта строка

Они структурированы таким образом, что идентификатор UserLogin представляет собой PK и FK для UserProfile, и то же самое относится к UserProfile

, первоначально, казалось, означало, что UserLoginимеет внешний ключ для UserProfile, и UserProfile имеет внешний ключ для UserLogin.Но теперь я думаю, что вы пытаетесь использовать одинаковые значения PK в обеих таблицах;если у меня есть UserLoginId = 123 и я затем создаю профиль, вы хотите, чтобы у меня был UserProfileId 123.

Почему вы это делаете?Это нормально с точки зрения базы данных (хотя я бы сказал, что это не особенно выгодно и несколько сбивает с толку), но LINQ-to-SQL хочет получить первичный ключ, который, как он знает, является первичным ключом для одной строки и не используется в качестве первичного ключа.для любого другого стола.И ему нужен внешний ключ, который также не является первичным ключом.

Значение 123 в таблице UserProfile на самом деле является внешним ключом для UserLogin, но не первичным ключом.Он не должен быть первичным ключом, и вы делаете вещи более запутанными для LINQ-to-SQL, делая это.Пусть UserProfile имеет свой собственный PK.Создайте автоинкрементную идентификацию и измените то, что у вас должно быть внешним ключом, обратно на UserLogin.Все ваши проблемы будут решены.

UserLogin
PK - UserLoginId int identity

UserProfile
PK - UserProfileId int identity
FK - UserLoginId int 

По моему опыту, и LINQ-to-SQL, и Entity Framework работают лучше всего с простыми суррогатными первичными ключами - независимо от всего остального.Что-то слишком сложное или нестандартное может причинить вам больше головной боли, чем любая очевидная выгода или простота.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...