2011-09-15 101 views
1

我目前正面临这个问题。我通过LINQ to SQL将POCO手动映射到我的数据库表中。我希望将所有这些对象/表放在一个上下文中(作为事务处理),以便在事务中出现故障时,所有对象都会回滚。LINQ to SQL 1:1插入

现在我面临的问题是我有UserLogin和UserProfile(1:0 - 1关系)。它们以UserLogin的ID为UserProfile的PK和FK的方式构建,UserProfile也是如此。在UserLogin上,它被设置为自动生成IsDBGenerated设置为true的标识。 UserProfile另一方面没有IsDBGenerated。

UserProfile在UserLogin中设置为EntityRef,并且由于它们来自同一个上下文,所以在创建时我会设置UserLogin.UserProfile = new UserProfile()。

分配所有属性后,我做了table.InsertOnSubmit(UserLogin)和context.SaveChanges()。

这是真正的问题用武之地。用户配置的ID仍然为0。

谁能帮助?


对不起,我没有说清楚。在使用中的SQL Server是MS SQL Server 2008的

的实体结构是这样的,

用户登陆是在注册时必需的,而用户配置不是,使其成为1:0 - 1的关系。因此,在两个表上都有自动增量是不明智的。

UserProfile的PK也是引用UserLogin的FK。

@GertArnold,是的,我没有在asp.net代码后面设置UserProfile id = UserLogin id,但在上下文保存之前,UserLogin的id将保持为0,因为此时我希望将两个记录添加到一起,想知道Linq to Sql是否有办法解决这个问题。因为我已经添加了Association属性,所以通过右边的Linq to Sql应该可以识别这个依赖关系,并在提交时添加该id,或者至少,这是我的一厢情愿。

在我的用户配置,我有这样的片段:

[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; } } 

在我的用户登陆,我有以下片段:

[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; 

此时,两个ID都为零,因为它们都没有被插入。

当我做context.SubmitChanges()时,UserLogin的id将得到递增的值,但UserProfile的id将保持为0.我想将两者包装在同一个上下文中并提交在一起的原因是为了避免像UserLogin这样的情况出现提交,但UserProfile发生错误。所以在我的数据库中,有一条登录记录,但没有配置文件,搞乱了我的数据。

+0

您使用的是哪种类型的数据库?由于UserProfile是UserLogin的子记录(至少在我看来是这样),为什么你不能只有UserProfile.Id是SqlServer中的一个AutoIncremting字段,如果它的Oracle ...添加一个序列...? – esastincy

回答

2

我不得不多次阅读这个问题,以了解你所得到的。这条线

他们的方式,其中用户登陆的ID是PK和FK到用户配置和同样的用户配置

结构最初似乎意味着UserLogin有一个外键UserProfileUserProfile有一个外键UserLogin。但是我现在认为你要做的是在两个表中使用相同的PK值;如果我有UserLoginId = 123,然后我创建一个配置文件,你希望我有UserProfileId 123.

你为什么要这样做?从数据库的角度来看没什么问题(尽管我认为这并不是特别有益,而且有点令人困惑),但是LINQ-to-SQL需要一个主键,它知道它是单个行的主键,而不是用作主键对于任何其他表格。它需要一个不是主键的外键。

UserProfile表中的值123实际上是UserLogin的外键,但不是主键。它不需要成为主键,因此您可以通过这样做让LINQ-to-SQL更容易混淆。让UserProfile有它自己的PK。创建一个自动递增的身份,并将您必须成为的外键改回UserLogin。你所有的问题都将得到解决。

UserLogin 
PK - UserLoginId int identity 

UserProfile 
PK - UserProfileId int identity 
FK - UserLoginId int 

以我的经验,无论是LINQ到SQL &实体框架的工作最好用简单的代理主键 - 独立的一切的。任何棘手或非标准的事情都可能会让你感到头痛,而不是任何感觉到的益处或简单。

+0

是的,你有这个权利。这正是我打算做的,使UserProfile的id = UserLogin的id,跳过代理键。在EF中,我能够通过流畅的API来实现这一目标,但不能在L2S中实现。不幸的是,这个项目仍然坚持L2S,如果我决定将其转换为EF4.1,那么这将会让我很难过,无论如何,我会向DBA建议您的方法,并看看我们如何从那里开始。谢谢。 –

+0

我有同样的问题(下面的链接),如果我将不得不这样做,那么我将失去关系数据库中的硬编码一对一关系。这意味着可以打破这个重要的限制。 http://stackoverflow.com/questions/10212290/linq-one-to-one-association-submitchanges – 2012-04-18 15:46:37

+0

@andicrook你的问题已被删除,所以我不能评论。但我并不完全同意 - 你仍然可以在外键列上添加一个唯一的约束来确保1:1。 –