user2286552
user2286552

Reputation:

EF Not including foreignkey uses the last object of the foreign type

EF 6, VS 2013, Local DB.

I have a very basic Entity Framework test project. It has Users and Blogs.

Every user can have many blogs, and a blog has a foreign key relating to the user.

I create a User, and a blog, but I don't connect them. EF made the connection without me telling it to.

If I don't create the User object, it errors as I wanted it to. I.e. don't save an object missing a required field.

public class FieldSizes
{
    public const int Names = 32;
    public const int Long = 80;
}

class Program
{
    static void Main(string[] args)
    {
        using(Dbf db = new Dbf())
        {
            var user = db.Users.Create();
            user.PasswordHash = "tests";
            user.UserName = "sssss";
            db.Users.Add(user);

            var blog = db.Blogs.Create();
            blog.Title = "gssss";
            blog.ContentId = 42;
            db.Blogs.Add(blog);
            db.SaveChanges();
        }
    }
}

public class Dbf : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Blog> Blogs { get; set; }
}

public class User
{
    [Key]
    public int Id { get; set; }

    [MaxLength(FieldSizes.Names)]
    public string UserName { get; set; }

    public string PasswordHash { get; set; }

    public void SetPassword(string password)
    {
        this.PasswordHash = "[Encryption Key]";
    }

    public virtual List<Blog> Blogs { get; set; }
}

public class Blog
{
    [Key]
    public int Id { get; set; }

    [ForeignKey("User")]
    public int UserId { get; set; }

    public virtual User User { get; set; }

    [MaxLength(FieldSizes.Long)]
    public string Title { get; set; }

    public int ContentId { get; set; }
}

Is this by design in EF? Is there a mistake in my code? I don't understand why EF is doing this.

Upvotes: 2

Views: 189

Answers (1)

Yuliam Chandra
Yuliam Chandra

Reputation: 14640

Yes, it's by design, but it's something that will be a problem if we're not aware about it.

When you created a new User, EF will assign a temporary key as primary key. The newly created User will have temporary Id = 0 since it's a default value of integer. The key is a temporary key and if it's an identity key, it will be updated after it's saved.

More: EntityKey.IsTemporary.

And when you created a new Blog, the default value of UserId is also 0. And it will cause Blog and User have relationship in the database.

You can also assign temporary key manually to make a relationship.

user.Id = 1234;
blog.UserId = 1234;

This is a great article explaining about this case. Here is part of the excerpt.

When creating a new relation we just need a dependent entity and a primary key of a parent entity. The tricky part here is that primary key must be unique for all attached entities of a given type. Even if we use auto generated keys in the database we must still assign temporary unique key to newly created entities which are added to relations.

Upvotes: 1

Related Questions