2

I have some issue that I can not solve. In my project I use EF6 Code First. I've created some models, but the head of them is User model:

 public class User
{
    [Required]
    public Guid Id { get; set; }
    [Required, MaxLength(20), MinLength(5), UniqProp] 
    public string Login { get; set; }
    [Required, MaxLength(20), MinLength(8)]
    public string Password { get; set; }
    [Required]
    public Role Role { get; set; }
    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    [Required, UniqProp]
    public string Email { get; set; }
    [Required]
    public string City { get; set; }
    public virtual List<Ticket> Tickets { get; set; } 
}

Also I've created my own context as shown below:

public class TheatreContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<Ticket> Tickets { get; set; }
    public DbSet<Play> Plays { get; set; }
}

After this I initialise my db in this way:

 using (var db = new TheatreContext())
 {
      Adding objects to db and save changes.
 }

At that moment everything works fine. All data was added to database. Then I've decided created my Repository class to make some operations with db:

public class TheatreRepository<T> : IRepository<T> where T: class
{
    private readonly TheatreContext _context;
    private readonly DbSet<T> _dbSet;

    public TheatreRepository()
    {
        _context = new TheatreContext();
        _dbSet = _context.Set<T>();
    }

    public void Add(T entity)
    { 
        _dbSet.Add(entity);
    }

    public DbSet<T> GetAll()
    {
        return this._dbSet;
    }

    public void Commit()
    { 
        _context.SaveChanges();
    }

And when I try to add new User in this way:

var repo = new TheatreRepository<User>();
var roleRepo = new TheatreRepository<Role>();

var newUser = new User
                  {
                      Id = Guid.NewGuid(),
                      Login = "Lionqweq",
                      City = "Minsk",
                      Role = roleRepo.GetAll().First(role => role.RoleType == RoleType.User),
                      FirstName = "Alex",
                      Email = "[email protected]",
                      Password = "dsas1qsqda",
                      LastName = "Ivanov"
                  };
repo.Add(newUser);
repo.Commit();

While calling Commit (SaveChanges in db) it throws DbUpdateException because I try to add to Role table object with existing Id. It doesn't make sense for me! Actually I didn't add any role, I've tried to add User only.

That what my Role table locally contains:

And that what I have in my Users table locally:

enter image description here

Please any suggestions and ideas! I got confused deeply

2 Answers 2

1

You should try instead of

[Required]
public Role Role { get; set; }

To use also use a reference to the FK:

[Required]
public Guid RoleId { get; set; }
public virtual Role Role { get; set; } 

When you create the a new user set only the RoleId

here is an example: EF first code

Sign up to request clarification or add additional context in comments.

1 Comment

Dear dany, thank you! You've helped me greatly! I've solved it in this way: public Guid RoleId { get; set; } [ForeignKey("RoleId")] public virtual Role Role { get; set; }
1

your problem is here

public TheatreRepository()
{
    _context = new TheatreContext();
    _dbSet = _context.Set<T>();
}

if you are implementing a repository pattern then your repository class must get the context in the constructor Which is know as DI, so it must be like that

public TheatreRepository(TheatreContext context)
{
    _context = context;
    _dbSet = _context.Set<T>();
} 

Explanation:

the repositories must use the same context to keep tracking of changes happening and loaded (local) entities so consider declaring your context before the repositories as below:

var db = new TheatreContext();
var repo = new TheatreRepository<User>(db);
var roleRepo = new TheatreRepository<Role>(db);
var newUser = new User
{
    Id = Guid.NewGuid(),
    Login = "Lionqweq",
    City = "Minsk",
    Role = roleRepo.GetAll().First(role => role.RoleType == RoleType.User),
    FirstName = "Alex",
    Email = "[email protected]",
    Password = "dsas1qsqda",
    LastName = "Ivanov"
};
repo.Add(newUser);
repo.Commit();

2 Comments

Are you saying they should both use the same instance of TheatreContext? (which isn't completely implied by 'must be dependency-injected')
So it means I can have only one context once created for all Repositories? If I'm right it means that for each table I will store my data Local too and I'll take quite much resources

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.