简体   繁体   English

主/明细表和实体框架存在问题

[英]Problem with master/detail tables and Entity Framework

I have a typical master/detail (User / Settings table) table schema (SQL Server) and setup Entity Framework using Fluent API to work with those tables. 我有一个典型的主/明细表(用户/设置表)表架构(SQL Server),并使用Fluent API设置实体框架来与这些表一起使用。

I define this as an independent association, so the UserProfileSetting class doesn't include the UserId property, but I understand is correctly mapped in the configuration. 我将其定义为一个独立的关联,因此UserProfileSetting类不包含UserId属性,但我知道在配置中已正确映射。

Well, my problem is that when one item of Settings is updated for a profile, at the database level that settings is updated for all users. 好吧,我的问题是,为配置文件更新一项Settings时,在数据库级别上所有用户的设置都会更新。 Basically USER_ID is not considered. 基本上不考虑USER_ID

The SQL query produced is this: 产生的SQL查询是这样的:

UPDATE [dbo].[T_USERPROFILE_SETTING]
SET [VALUE] = @0
WHERE ([KEY] = @1)

Any idea what could be wrong? 知道有什么问题吗? I guess that if I finally add the UserId property to UserProfileSettings , that will fix the problem, but I wanted to try to fix this without it. 我猜想,如果我最终将UserId属性添加到UserProfileSettings ,将解决此问题,但是我想尝试在没有此问题的情况下解决此问题。

Current code below... 当前代码如下...

Code updating the data 代码更新数据

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();

Entities: 实体:

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

Entity configuration: 实体配置:

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();
    }
}

From EF documentation ... EF文档 ...

When foreign key columns are not included in the model, the association information is managed as an independent object. 当模型中不包含外键列时,关联信息将作为独立对象进行管理。 Relationships are tracked through object references instead of foreign key properties. 通过对象引用而不是外键属性来跟踪关系。 This type of association is called an independent association. 这种关联称为独立关联。 The most common way to modify an independent association is to modify the navigation properties that are generated for each entity that participates in the association. 修改独立关联的最常见方法是修改为参与该关联的每个实体生成的导航属性。

So, I was wrong. 所以,我错了。 In my code, UserProfile should include UserProfileSetting either as a FK (Just the ID) or as an independent Object. 在我的代码中,UserProfile应该将UserProfileSetting包含为FK(仅ID)或独立的Object。

  • In the 1st case a UserId should be mapped into UserProfileSetting and the navigation property in UserProfile should be changed to... 在第一种情况下,应将UserId映射到UserProfileSetting中,并将UserProfile中的导航属性更改为...

    HasMany<UserProfileSetting>(p => p.Settings) .WithOptional() .HasForeignKey(s => s.UserId);

  • In the 2nd case, (this is what is called an Independent Association ) a new navigation property should be added into UserProfileSetting for UserProfile. 在第二种情况下(这是所谓的独立协会 ),应将新的导航属性添加到UserProfile的UserProfileSetting中。

Entity framework maps to relational database and so it must stick with some of it concepts. 实体框架映射到关系数据库,因此它必须坚持其中的一些概念。 The main thing here is, that each entity is mapped to a table containing all the records of that entity and it needs some data to distinguish the relation. 这里最主要的是,每个实体都映射到包含该实体的所有记录的表,并且它需要一些数据来区分关系。

Therefore you need to add USER_ID to tell which record is for which user (to define the relation). 因此,您需要添加USER_ID来告诉哪个用户的记录(定义关系)。 In other words you need to have it in table and also in C# entity. 换句话说,您需要在表中以及C#实体中都有它。

I don't think it is possible in code first to not have the relation property on entity. 我认为在代码中首先没有实体上的关系属性是不可能的。 On the other hand, you can create some extra DTO layer to hide it. 另一方面,您可以创建一些额外的DTO图层以将其隐藏。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM