master/detail 表和 Entity Framework 有问题
Problem with master/detail tables and Entity Framework
我有一个典型的 master/detail(用户/设置 table)table 架构(SQL 服务器)并使用 Fluent [=48] 设置 Entity Framework =] 与那些 tables.
一起工作
我将其定义为独立关联,因此 UserProfileSetting
class 不包括 UserId
属性,但我理解在配置中正确映射.
好吧,我的问题是,当 Settings
的一项针对个人资料更新时,在数据库级别,所有用户的设置都会更新。基本上USER_ID
不考虑。
生成的 SQL 查询是这样的:
UPDATE [dbo].[T_USERPROFILE_SETTING]
SET [VALUE] = @0
WHERE ([KEY] = @1)
知道哪里出了问题吗?我想如果我最终将 UserId
属性 添加到 UserProfileSettings
,那将解决问题,但我想尝试在没有它的情况下解决这个问题。
当前代码如下...
更新数据的代码
var entry = profile.Settings.Where(s => s.Key == key).SingleOrDefault();
if (entry != null)
{
entry.Value = value;
} else {
var setting = /* Here create a new setting */
profile.Settings.Add(setting);
}
DataContext.SaveChanges();
实体:
public partial class UserProfile
{
[Key]
public string UserId { get; set; }
public DateTimeOffset LastLogin { get; set; }
public ICollection<UserProfileSetting> Settings { get; set; }
}
public class UserProfileSetting
{
public UserProfileSetting() { }
public string Key { get; set; }
public string Value { get; set; }
}
实体配置:
public class UserProfileConfiguration : EntityTypeConfiguration<UserProfile>
{
public UserProfileConfiguration()
{
ToTable("T_USERPROFILE");
HasKey<string>(p => p.UserId);
Property(p => p.UserId)
.HasColumnName("USER_ID")
.HasMaxLength(50)
.IsUnicode()
.IsRequired();
Property(p => p.LastLogin)
.HasColumnName("LAST_LOGIN_AT")
.IsRequired();
HasMany<UserProfileSetting>(p => p.Settings)
.WithOptional()
.Map(m => m.MapKey("USER_ID"));
}
}
public class UserProfileSettingConfiguration : EntityTypeConfiguration<UserProfileSetting>
{
public UserProfileSettingConfiguration()
{
ToTable("T_USERPROFILE_SETTING");
HasKey(p => p.Key );
Property(p => p.Key)
.HasColumnName("KEY")
.HasMaxLength(50)
.IsUnicode()
.IsRequired();
Property(p => p.Value)
.HasColumnName("VALUE")
.IsUnicode()
.IsRequired();
}
}
Entity framework 映射到关系数据库,因此它必须坚持一些概念。这里最主要的是,每个实体都映射到一个 table 包含该实体的所有记录,它需要一些数据来区分关系。
因此您需要添加 USER_ID 来告诉哪个记录是哪个用户(定义关系)。换句话说,您需要在 table 和 C# 实体中使用它。
我认为在代码优先中不可能在实体上没有关系 属性。另一方面,您可以创建一些额外的 DTO 层来隐藏它。
从EF documentation...
当模型中不包含外键列时,关联信息作为一个独立的对象进行管理。通过对象引用而不是外键属性来跟踪关系。这种类型的协会称为独立协会。修改独立关联的最常见方法是修改为参与关联的每个实体生成的导航属性。
所以,我错了。在我的代码中,UserProfile 应将 UserProfileSetting 作为 FK(仅 ID)或作为独立对象包含。
在第一种情况下,应将 UserId 映射到 UserProfileSetting 并将 UserProfile 中的导航 属性 更改为...
HasMany<UserProfileSetting>(p => p.Settings)
.WithOptional()
.HasForeignKey(s => s.UserId);
第二种情况,(这就是所谓的独立关联)应该在UserProfile的UserProfileSetting中添加一个新的导航属性 .
我有一个典型的 master/detail(用户/设置 table)table 架构(SQL 服务器)并使用 Fluent [=48] 设置 Entity Framework =] 与那些 tables.
一起工作我将其定义为独立关联,因此 UserProfileSetting
class 不包括 UserId
属性,但我理解在配置中正确映射.
好吧,我的问题是,当 Settings
的一项针对个人资料更新时,在数据库级别,所有用户的设置都会更新。基本上USER_ID
不考虑。
生成的 SQL 查询是这样的:
UPDATE [dbo].[T_USERPROFILE_SETTING]
SET [VALUE] = @0
WHERE ([KEY] = @1)
知道哪里出了问题吗?我想如果我最终将 UserId
属性 添加到 UserProfileSettings
,那将解决问题,但我想尝试在没有它的情况下解决这个问题。
当前代码如下...
更新数据的代码
var entry = profile.Settings.Where(s => s.Key == key).SingleOrDefault();
if (entry != null)
{
entry.Value = value;
} else {
var setting = /* Here create a new setting */
profile.Settings.Add(setting);
}
DataContext.SaveChanges();
实体:
public partial class UserProfile
{
[Key]
public string UserId { get; set; }
public DateTimeOffset LastLogin { get; set; }
public ICollection<UserProfileSetting> Settings { get; set; }
}
public class UserProfileSetting
{
public UserProfileSetting() { }
public string Key { get; set; }
public string Value { get; set; }
}
实体配置:
public class UserProfileConfiguration : EntityTypeConfiguration<UserProfile>
{
public UserProfileConfiguration()
{
ToTable("T_USERPROFILE");
HasKey<string>(p => p.UserId);
Property(p => p.UserId)
.HasColumnName("USER_ID")
.HasMaxLength(50)
.IsUnicode()
.IsRequired();
Property(p => p.LastLogin)
.HasColumnName("LAST_LOGIN_AT")
.IsRequired();
HasMany<UserProfileSetting>(p => p.Settings)
.WithOptional()
.Map(m => m.MapKey("USER_ID"));
}
}
public class UserProfileSettingConfiguration : EntityTypeConfiguration<UserProfileSetting>
{
public UserProfileSettingConfiguration()
{
ToTable("T_USERPROFILE_SETTING");
HasKey(p => p.Key );
Property(p => p.Key)
.HasColumnName("KEY")
.HasMaxLength(50)
.IsUnicode()
.IsRequired();
Property(p => p.Value)
.HasColumnName("VALUE")
.IsUnicode()
.IsRequired();
}
}
Entity framework 映射到关系数据库,因此它必须坚持一些概念。这里最主要的是,每个实体都映射到一个 table 包含该实体的所有记录,它需要一些数据来区分关系。
因此您需要添加 USER_ID 来告诉哪个记录是哪个用户(定义关系)。换句话说,您需要在 table 和 C# 实体中使用它。
我认为在代码优先中不可能在实体上没有关系 属性。另一方面,您可以创建一些额外的 DTO 层来隐藏它。
从EF documentation...
当模型中不包含外键列时,关联信息作为一个独立的对象进行管理。通过对象引用而不是外键属性来跟踪关系。这种类型的协会称为独立协会。修改独立关联的最常见方法是修改为参与关联的每个实体生成的导航属性。
所以,我错了。在我的代码中,UserProfile 应将 UserProfileSetting 作为 FK(仅 ID)或作为独立对象包含。
在第一种情况下,应将 UserId 映射到 UserProfileSetting 并将 UserProfile 中的导航 属性 更改为...
HasMany<UserProfileSetting>(p => p.Settings) .WithOptional() .HasForeignKey(s => s.UserId);
第二种情况,(这就是所谓的独立关联)应该在UserProfile的UserProfileSetting中添加一个新的导航属性 .