简体   繁体   中英

Entity splitting across three tables with two different keys?

I have the following database schema which I can't change:

数据库架构

The relationship between the TM_USER and TM_USER_DETAIL tables uses the USR_ID and UDT_USR_ID columns. The data type of USR_ID is int .

The relationship between the TM_USER and TM_MEMBERSHIP_USERS tables uses the USR_USER_KEY and USR_ID columns. The data type of USR_USER_KEY is a guid represented as a string .

My question is how to map this using Entity Framework?

Here is my entity:

public class User
{
    // from table TM_USER
    public int Id { get; set; }
    public string Username { get; set; }
    public string Key { get; set; }

    // from table TM_USER_DETAIL
    public string Forename { get; set; }
    public string Surname { get; set; }

    // from table TM_MEMBERSHIP_USERS
    public bool IsApproved { get; set; }
}

And my entity configuration:

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        Map(map =>
        {
            map.Properties(p => new { p.Key, p.Id, p.Username });

            map.ToTable("TM_USER");

            map.Property(p => p.Key).HasColumnName("USR_USER_KEY");
            map.Property(p => p.Id).HasColumnName("USR_ID");
            map.Property(p => p.Username).HasColumnName("USR_USER_NAME");
        });

        Map(map =>
        {
            map.Properties(p => new { p.Forename, p.Surname });

            map.ToTable("TM_USER_DETAIL");

            map.Property(p => p.Id).HasColumnName("UDT_USR_ID");
            map.Property(p => p.Forename).HasColumnName("UDT_FORENAME");
            map.Property(p => p.Surname).HasColumnName("UDT_SURNAME");
        });

        Map(map =>
        {
            map.Properties(p => new { p.IsApproved });

            map.ToTable("TM_MEMBERSHIP_USERS");

            map.Property(p => p.Key).HasColumnName("USR_ID");
            map.Property(p => p.IsApproved).HasColumnName("USR_ISAPPROVED");
        });

        HasKey(user => user.Id);
    }
}

When I try to query the Users , I get the following error:

Properties for type 'User' can only be mapped once. The non-key property 'Id' is mapped more than once. Ensure the Properties method specifies each non-key property only once.

Is it possible to configure EF to map a single entity to three tables in this way using different keys for each relationship?

I have posted a sample solution here: https://github.com/kevinkuszyk/entity-splitting

This is not possible. You should split your model into different models. Furthermore, the relationship does not make sense for me. In your schema, TM_USER has many TM_USER_DETAIL , that relationship allows an User to have several forenames and surnames. I think that was not your intention. In a common scenario, the TM_USER has only one TM_USER_DETAIL . So, your model should be something like this:

TM_USER
-------------
UserId - PK
Username 
Key 
Deleted

TM_USER_DETAIL
---------------
UserId - PK - FK TM_USER
Forename 
Surname 

To make the model even simpler, we can merge TM_USER_DETAIL with TM_USER . Like this:

TM_USER
-------------
UserId - PK
Username 
Key 
Forename 
Surname 
Deleted

The same thing values to the relationship between TM_User and TM_MEMBERSHIP_USERS . So, we can merge them. Like this:

TM_USER
-------------
UserId - PK
Username 
Key 
Forename 
Surname
IsApproved  
Deleted

Now, we have to create the User class in order to use it in the Entity Framework.

public class User
{
    // from table TM_USER 
    public int Id { get; set; }
    public string Username { get; set; }
    public string Key { get; set; }


    public string Forename { get; set; }
    public string Surname { get; set; }

    public bool IsApproved { get; set; }
}

Mapping:

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        ToTable("TM_USER");

        Property(p => p.Key).HasColumnName("USR_USER_KEY");
        Property(p => p.Id).HasColumnName("USR_ID");
        Property(p => p.Username).HasColumnName("USR_USER_NAME");
        Property(p => p.Forename).HasColumnName("UDT_FORENAME");
        Property(p => p.Surname).HasColumnName("UDT_SURNAME");
        Property(p => p.IsApproved).HasColumnName("USR_ISAPPROVED");

        HasKey(user => user.Id);
    }
}

If you still want to use 3 different tables, you have to create 3 different classes, with their respective properties, mapping them to their respective tables.

Hope it helps!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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