简体   繁体   中英

Entity Framework throws invalid column name User_Id error

I am trying to create and associate the entities in my project. The User can have many Roles, Claims and Logins. On the other hand, A claim or login can have only one user, while a role can also be with many user. I have the relationship defined with fluent API:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    modelBuilder.Entity<User>().HasMany(u => u.Claims).WithRequired(cl => cl.User).Map(m => m.MapKey("User"));
    modelBuilder.Entity<Claim>().HasRequired(cl => cl.User).WithMany(u => u.Claims).Map(m => m.MapKey("User"));

    modelBuilder.Entity<User>().HasMany(u => u.Logins).WithRequired(lg => lg.User).Map(m => m.MapKey("User"));
    modelBuilder.Entity<Login>().HasRequired(lg => lg.User).WithMany(u => u.Logins).Map(m => m.MapKey("User"));

    modelBuilder.Entity<User>().HasMany(u => u.Roles).WithMany(ro => ro.Users).Map(userRoles => 
    {
        userRoles.ToTable("Users_Roles");
        userRoles.MapLeftKey("User");
        userRoles.MapRightKey("Role");
    });     

    modelBuilder.Entity<Role>().HasMany(ro => ro.Users).WithMany(u => u.Roles).Map(userRoles => 
    {
        userRoles.ToTable("Users_Roles");
        userRoles.MapLeftKey("User");
        userRoles.MapRightKey("Role");
    }); 
}

As you see, my database tables do not follow Entity Framework's convention, instead of using 'User_Id' as foreign key, the foreign key is simply named 'User'. However, I keep getting this 'Invalid Column Name: User_Id' exception message.

I tried to define the foreign key column name with the above code by calling the methods Map() and MapKey(), but with no prevail. Why is this happening? Am I writing the mapping code wrong? Can someone help?

PS: The exception error message is very unhelpful that I do not know which table this column name error is associated with. Does anyone know how to make the exception message show what the table name is, not just the column name? Thanks.

Also I've added code I used for Claim, Login and Role entities(with unrelated methods removed).

public class Claim
{
    public string Id { get; protected set; }
    public string Type { get; protected set; }
    public string Value { get; protected set; }

    public virtual User User { get; protected set; }

    public Claim() { }

    public Claim(string id, User user, string type, string value)
    {
        Id = id;
        User = user;
        Type = type;
        Value = value;
    }
}

public class Login
{
    public string Id { get; protected set; }
    public string Provider { get; protected set; }
    public string Key { get; protected set; }
    public DateTime? DateLoggedin { get; protected set; }

    public virtual User User { get; protected set; }

    public Login() { }

    public Login(string id, string provider, string key, DateTime? dateLoggedIn = null)
    {
        Id = id;
        Provider = provider;
        Key = key;
        DateLoggedin = dateLoggedIn;
    }
}

public class Role
{
    public string Id { get; protected set; }
    public string Title { get; protected set; }
    public string Description { get; protected set; }
    public bool IsAdmin { get; protected set; }
    public bool IsBanned { get; protected set; }

    public IList<User> Users { get; protected set; }

    public Role() { }

    public Role(string id, string title, string description, bool isAdmin, bool isBanned)
    {
        Id = id;
        Title = title;
        Description = description;
        IsAdmin = isAdmin;
        IsBanned = isBanned;
    }
}

The User_Id column is being created by EF convention because you map your key to a property by the same name as your navigation proeprty.

You could either remove the .Map() part and let EF handle the key, or define a key property on your Claim and Login classes, and map that in the fluent api. I would personally do the latter.

Eg:

public class Claim
{
public string Id { get; protected set; }
public string Type { get; protected set; }
public string Value { get; protected set; }

public virtual User User { get; protected set; }
public int UserId{get;set;}
public Claim() { }
}

And in your ModelCreating

modelBuilder.Entity<User>().HasMany(a=>a.Claims).WithRequired(a=>a.User).HasForeignKey(a=>a.UserId);

If you create a key field of 'EntityNameId' (UserId, ClaimId, etc) then EF convention will automatically map that as your Foreign Key, without the fluent mapping. However, if you name is something else (UsernameId, or whatever), you have to explicitly provide the mapping. Some reading on that.

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