【问题标题】:Entity Framework Add User to Role实体框架将用户添加到角色
【发布时间】:2015-01-02 06:53:56
【问题描述】:

我之前问过一个问题是answered here

基本上我需要 2 个类:

public class User : IUser
{
    public string Id { get; set; }

    // Stripped for brevity

    public IList<Role> Roles { get; set; }

    public User()
    {
        this.Id = Guid.NewGuid().ToString();
    }
}

public class Role : IRole
{
    public string Id { get; set; }
    public string Name { get; set; }

    public Role()
    {
        this.Id = Guid.NewGuid().ToString();
    }
}

在我的 DbContext 我有这样的声明:

modelBuilder.Entity<User>()
    .HasMany(m => m.Roles)
    .WithMany()
    .Map(m => { 
        m.MapLeftKey("UserId");
        m.MapRightKey("RoleId"); 
        m.ToTable("UserRoles"); 
    });

这一切都很完美。现在,我想将用户添加到特定角色,因此我按照我的服务/存储库/工作单元设计模式创建了一个服务,如下所示:

public class UserRoleService : Service<UserRole>
{
    public UserRoleService(IUnitOfWork unitOfWork)
        : base(unitOfWork)
    {

    }

    public async Task<IList<UserRole>> GetAllAsync(string userId, params string[] includes)
    {
        return await this.Repository.GetAll(includes).Where(m => m.UserId.Equals(userId, StringComparison.OrdinalIgnoreCase)).ToListAsync();
    }

    public async Task CreateAsync(UserRole model)
    {
        var isInRole = await IsInRole(model.UserId, model.RoleId);

        if (isInRole)
            throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.UserInRole, new object[] { model.RoleId }));

        this.Repository.Create(model);
    }

    public async Task RemoveAsync(UserRole model)
    {
        var isInRole = await IsInRole(model.UserId, model.RoleId);

        if (!isInRole)
            throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, Resources.UserNotInRole, new object[] { model.RoleId }));

        this.Repository.Remove(model);
    }

    public async Task<bool> IsInRole(string userId, string roleId)
    {
        if (string.IsNullOrEmpty(userId))
            throw new ArgumentNullException("userId");

        if (string.IsNullOrEmpty(userId))
            throw new ArgumentNullException("roleId");

        var roles = await this.GetAllAsync(userId);
        var match = roles.Where(m => m.RoleId.Equals(roleId, StringComparison.OrdinalIgnoreCase)).SingleOrDefault();

        return (match == null);
    }
}

继承的服务类如下所示:

public class Service<T> where T : class
{
    private readonly IRepository<T> repository;

    protected IRepository<T> Repository
    {
        get { return this.repository; }
    }

    public Service(IUnitOfWork unitOfWork)
    {
        if (unitOfWork == null)
            throw new ArgumentNullException("unitOfWork");

        this.repository = unitOfWork.GetRepository<T>();
    }
}

现在,因为我的 DbContext 没有用于 UserRolesDbSet,它会抱怨,所以我添加了一个。然后我抱怨说新表没有设置主键,所以我添加了一个。所以现在我的 DbContext 看起来像这样:

public class DatabaseContext : DbContext
{
    // Removed for brevity
    public DbSet<Role> Roles { get; set; }
    public DbSet<User> Users { get; set; }
    public DbSet<UserRole> UserRoles { get; set; }

    static DatabaseContext()
    {
        //Database.SetInitializer<IdentityContext>(null); // Exsting database, do nothing (Comment out to create database)
    }

    public DatabaseContext()
        : base("DefaultConnection")
    {
        base.Configuration.LazyLoadingEnabled = false; // Disable Lazy Loading
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); // Remove Cascading Delete

        // Removed from brevity
        modelBuilder.Entity<UserRole>().HasKey(m => new { m.UserId, m.RoleId });
        modelBuilder.Entity<User>()
            .HasMany(m => m.Roles)
            .WithMany()
            .Map(m => { 
                m.MapLeftKey("UserId");
                m.MapRightKey("RoleId"); 
                m.ToTable("UserRoles"); 
            });
    }
}

我现在遇到的问题是,我的代码为 UserRole 创建了两个表,分别称为 UserRolesUserRoles1。 谁能告诉我如何让它只使用一张桌子?

【问题讨论】:

  • 你用过会员吗?
  • 您的用户有角色,但您的角色没有用户。因此,在您的上下文中,将用户添加到角色中并不明显。构建您的语言以匹配您的数据模型,或构建您的数据模型以匹配您的语言。

标签: c# entity-framework


【解决方案1】:

如果 UserRole 表示一个纯映射(即它只包含 UserId 和 RoleId,没有其他属性),那么您实际上不需要 UserRole 对象。在您的 DbContext 中定义关系就足够了(您已经完成了)。要将特定角色与特定用户关联,您只需执行以下操作:

user.Roles.Add(role);

...并提交 DbSet

Entity Framework 足够智能,可以为您维护多对多映射表,而无需实际拥有表示映射本身的实体。

注意:您尝试添加的角色对象必须是数据库上下文中的实体。如果您尝试创建角色实体然后分配,EF 将尝试插入(并且可能由于主键违规而失败)。

【讨论】:

  • 太棒了 :) 我目前唯一的问题是它似乎没有保存,但我会为此再发一篇文章。
  • 想通了,不用再问了:)
猜你喜欢
  • 2015-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-14
  • 2011-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多