AspNetCore.Identity,MySQL数据库,已经打开DataReader,UserManager和RoleManager

时间:2016-12-16 15:06:08

标签: asp.net

我正在使用用户身份验证创建一个Web应用程序。

我使用Microsoft.AspNetCore.Identity.EntityFrameworkCore UserManager<IdentityUser>RoleManager<IdentityRole>来管理用户及其角色。

当我在连接字符串中使用带有MultipleActiveResultSets=true的Visual Studio中的localDB功能时,一切正常。

当我想使用安装在我的Ubuntu 16.04服务器上的MySQL服务器时,我可以登录。但是,只要RoleManager首次尝试连接到数据库,就会出现以下错误:

  

MySqlException:已经有一个打开的DataReader与之关联   这个必须先关闭的连接

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using tsv_core.Models;

    // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860

    namespace tsv_core.Controllers
    {
        [Authorize(Roles = "Admins")]
        public class AdminController : Controller
        {
            UserManager<AppUser> userManager;
            private IUserValidator<AppUser> userValidator;
            private IPasswordValidator<AppUser> passwordValidator;
            private IPasswordHasher<AppUser> passwordHasher;
            private IRequestLogger _logger;

            public AdminController(UserManager<AppUser> usrMgr, IUserValidator<AppUser> userValid, IPasswordValidator<AppUser> passValid, IPasswordHasher<AppUser> passwordHash, IRequestLogger logger)
            {
                userManager = usrMgr;
                userValidator = userValid;
                passwordValidator = passValid;
                passwordHasher = passwordHash;
                _logger = logger;
            }

            public ViewResult Accounts() => View(userManager.Users);

            public ViewResult Create() => View();
            [HttpPost]
            public async Task<IActionResult> Create(CreateModel model)
            {
                if (ModelState.IsValid)
                {
                    AppUser user = new AppUser
                    {
                        UserName = model.Name,
                        Email = model.Email
                    };
                    IdentityResult result
                    = await userManager.CreateAsync(user, model.Password);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Accounts");
                    }
                    else
                    {
                        foreach (IdentityError error in result.Errors)
                        {
                            ModelState.AddModelError("", error.Description);
                        }
                    }
                }
                return View(model);
            }

            [HttpPost]
            public async Task<IActionResult> Delete(string id)
            {
                AppUser user = await userManager.FindByIdAsync(id);
                if (user != null)
                {
                    IdentityResult result = await userManager.DeleteAsync(user);
                    if (result.Succeeded)
                    {
                        return RedirectToAction("Index");
                    }
                    else
                    {
                        AddErrorsFromResult(result);
                    }
                }
                else
                {
                    ModelState.AddModelError("", "User Not Found");
                }
                return View("Index", userManager.Users);
            }

            public async Task<IActionResult> Edit(string id)
            {
                AppUser user = await userManager.FindByIdAsync(id);
                if (user != null)
                {
                    return View(user);
                }
                else
                {
                    return RedirectToAction("Index");
                }
            }
            [HttpPost]
            public async Task<IActionResult> Edit(string id, string email,
            string password)
            {
                AppUser user = await userManager.FindByIdAsync(id);
                if (user != null)
                {
                    user.Email = email;
                    IdentityResult validEmail
                    = await userValidator.ValidateAsync(userManager, 

user);
                        if (!validEmail.Succeeded)
                        {
                            AddErrorsFromResult(validEmail);
                        }
                        IdentityResult validPass = null;
                        if (!string.IsNullOrEmpty(password))
                        {
                            validPass = await passwordValidator.ValidateAsync(userManager,
                            user, password);
                            if (validPass.Succeeded)
                            {
                                user.PasswordHash = passwordHasher.HashPassword(user,
                                password);
                            }
                            else
                            {
                                AddErrorsFromResult(validPass);
                            }
                        }
                        if ((validEmail.Succeeded && validPass == null)
                        || (validEmail.Succeeded
                        && password != string.Empty && validPass.Succeeded))
                        {
                            IdentityResult result = await userManager.UpdateAsync(user);
                            if (result.Succeeded)
                            {
                                return RedirectToAction("Index");
                            }
                            else
                            {
                                AddErrorsFromResult(result);
                            }
                        }
                    }
                    else
                    {
                        ModelState.AddModelError("", "User Not Found");
                    }
                    return View(user);
                }

                private void AddErrorsFromResult(IdentityResult result)
                {
                    foreach (IdentityError error in result.Errors)
                    {
                        ModelState.AddModelError("", error.Description);
                    }
                }

                public ViewResult RequestLogging()
                {
                    return View(_logger.GetRequestRepository());
                }
            }
        }

    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using tsv_core.Models;
    using Microsoft.AspNetCore.Identity;

    namespace tsv_core.Controllers
    {
        [Authorize(Roles = "Admins")]
        public class AccountController : Controller
        {
            private UserManager<AppUser> userManager;
            private SignInManager<AppUser> signInManager;
            public AccountController(UserManager<AppUser> userMgr,
            SignInManager<AppUser> signinMgr)
            {
                userManager = userMgr;
                signInManager = signinMgr;
            }
            [AllowAnonymous]
            public IActionResult Login(string returnUrl)
            {
                ViewBag.returnUrl = returnUrl;
                return View();
            }
            [HttpPost]
            [AllowAnonymous]
            [ValidateAntiForgeryToken]
            public async Task<IActionResult> Login(LoginModel details,
            string returnUrl)
            {
                if (ModelState.IsValid)
                {
                    AppUser user = await userManager.FindByEmailAsync(details.Email);
                    if (user != null)
                    {
                        await signInManager.SignOutAsync();
                        Microsoft.AspNetCore.Identity.SignInResult result =
                        await signInManager.PasswordSignInAsync(
                        user, details.Password, false, false);
                        if (result.Succeeded)
                        {
                            return Redirect(returnUrl ?? "/");
                        }
                    }
                    ModelState.AddModelError(nameof(LoginModel.Email), "Invalid user or password");
                }
                return View(details);
            }

            public async Task<IActionResult> Logout()
            {
                await signInManager.SignOutAsync();
                return RedirectToAction("Index", "Home");
            }

            [AllowAnonymous]
            public IActionResult AccessDenied()
            {
                return View();
            }
        }
    }

using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using tsv_core.Models;
using System.Collections.Generic;
using Microsoft.AspNetCore.Authorization;

namespace tsv_core.Controllers
{
    [Authorize(Roles = "Admins")]
    public class RoleAdminController : Controller
    {
        private RoleManager<IdentityRole> roleManager;
        private UserManager<AppUser> userManager;
        public RoleAdminController(RoleManager<IdentityRole> roleMgr, UserManager<AppUser> userMrg)
        {
            roleManager = roleMgr;
            userManager = userMrg;
        }
        public ViewResult Index() => View(roleManager.Roles);
        public IActionResult Create() => View();
        [HttpPost]
        public async Task<IActionResult> Create([Required]string name)
        {
            if (ModelState.IsValid)
            {
                IdentityResult result
                = await roleManager.CreateAsync(new IdentityRole(name));
                if (result.Succeeded)
                {
                    return RedirectToAction("Index");
                }
                else
                {
                    AddErrorsFromResult(result);
                }
            }
            return View(name);
        }
        [HttpPost]
        public async Task<IActionResult> Delete(string id)
        {
            IdentityRole role = await roleManager.FindByIdAsync(id);
            if (role != null)
            {
                IdentityResult result = await roleManager.DeleteAsync(role);
                if (result.Succeeded)
                {
                    return RedirectToAction("Index");
                }
                else
                {
                    AddErrorsFromResult(result);
                }
            }
            else
            {
                ModelState.AddModelError("", "No role found");
            }
            return View("Index", roleManager.Roles);
        }

        public async Task<IActionResult> Edit(string id)
        {
            IdentityRole role = await roleManager.FindByIdAsync(id);
            List<AppUser> members = new List<AppUser>();
            List<AppUser> nonMembers = new List<AppUser>();
            foreach (AppUser user in userManager.Users)
            {
                var list = await userManager.IsInRoleAsync(user, role.Name)
                ? members : nonMembers;
                list.Add(user);
            }
            return View(new RoleEditModel
            {
                Role = role,
                Members = members,
                NonMembers = nonMembers
            });
        }
        [HttpPost]
        public async Task<IActionResult> Edit(RoleModificationModel model)
        {
            IdentityResult result;
            if (ModelState.IsValid)
            {
                foreach (string userId in model.IdsToAdd ?? new string[] { })
                {
                    AppUser user = await userManager.FindByIdAsync(userId);
                    if (user != null)
                    {
                        result = await userManager.AddToRoleAsync(user,
                        model.RoleName);
                        if (!result.Succeeded)
                        {
                            AddErrorsFromResult(result);
                        }
                    }
                }
                foreach (string userId in model.IdsToDelete ?? new string[] { })
                {
                    AppUser user = await userManager.FindByIdAsync(userId);
                    if (user != null)
                    {
                        result = await userManager.RemoveFromRoleAsync(user,
                        model.RoleName);
                        if (!result.Succeeded)
                        {
                            AddErrorsFromResult(result);
                        }
                    }
                }
            }
            if (ModelState.IsValid)
            {
                return RedirectToAction(nameof(Index));
            }
            else
            {
                return await Edit(model.RoleId);
            }
        }

        private void AddErrorsFromResult(IdentityResult result)
        {
            foreach (IdentityError error in result.Errors)
            {
                ModelState.AddModelError("", error.Description);
            }
        }
    }
}

using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Razor.TagHelpers;
using tsv_core.Models;

namespace tsv_core.Infrastructure
{
    [HtmlTargetElement("td", Attributes = "identity-role")]
    public class RoleUsersTagHelper : TagHelper
    {
        private UserManager<AppUser> userManager;
        private RoleManager<IdentityRole> roleManager;
        public RoleUsersTagHelper(UserManager<AppUser> usermgr,
        RoleManager<IdentityRole> rolemgr)
        {
            userManager = usermgr;
            roleManager = rolemgr;
        }
        [HtmlAttributeName("identity-role")]
        public string Role { get; set; }
        public override async Task ProcessAsync(TagHelperContext context,
        TagHelperOutput output)
        {
            IdentityRole role = await roleManager.FindByIdAsync(Role);;
            List<string> names = new List<string>();

                if (role != null)
                {
                    foreach (var user in userManager.Users)
                    {
                        if (user != null && await userManager.IsInRoleAsync(user, role.Name))
                        {
                            names.Add(user.UserName);
                        }
                    }
                }
                output.Content.SetContent(names.Count == 0 ?
                "No Users" : string.Join(", ", names));           
        }
    }
}

@model IEnumerable<IdentityRole>
<div class="bg-primary panel-body"><h4>Roles</h4></div>
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<table class="table table-condensed table-bordered table-bordered">
    <tr><th>ID</th><th>Name</th><th>Users</th><th></th></tr>
    @if (Model.Count() == 0)
    {
        <tr><td colspan="4" class="text-center">No Roles</td></tr>
    }
    else
    {
        foreach (var role in Model)
        {
            <tr>
                <td>@role.Id</td>
                <td>@role.Name</td>
                <td identity-role="@role.Id"></td>
                <td>
                    <form asp-action="Delete" asp-route-id="@role.Id" method="post">
                        <a class="btn btn-sm btn-primary" asp-action="Edit"
                           asp-route-id="@role.Id">Edit</a>
                        <button type="submit"
                                class="btn btn-sm btn-danger">
                            Delete
                        </button>
                    </form>
                </td>
            </tr>
        }
    }
</table>
    <a class="btn btn-primary" asp-action="Create">Create</a>

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using tsv_core.Models;
using tsv_core.Infrastructure;
using MySQL.Data.EntityFrameworkCore.Extensions;

namespace tsv_core
{
    public class Startup
    {
        IConfigurationRoot Configuration;
        public Startup(IHostingEnvironment env)
        {
            Configuration = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json").Build();
        }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddDbContext<AppIdentityDbContext>(options => options.UseSqlServer(Configuration["Data:tsvIdentity:ConnectionString"]));
            services.AddDbContext<AppIdentityDbContext>(options => options.UseMySQL(Configuration["Data:tsvIdentity:ConnectionString"]));
            services.AddIdentity<AppUser, IdentityRole>(opts => opts.User.RequireUniqueEmail = true).AddEntityFrameworkStores<AppIdentityDbContext>();

            services.AddTransient<IRequestLogger, TestRequestLogger>();
            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
                loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                loggerFactory.AddDebug();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();
            app.UseIdentity();

            //This position of the LoggingMiddleware is important!! If it would be placed before "app.UseStaticFiles();" the request paths to the static files would be logged too.
            //If it would be placed behind app.UseMvc, it wouldn't log anything at all.            
            app.UseMiddleware<LoggingMiddleware>();

            app.UseMvcWithDefaultRoute();

            AppIdentityDbContext.CreateAdminAccount(app.ApplicationServices, Configuration).Wait();
        }
    }
}

这些应该是所有相关的类。

AppUser只是继承自IdentityUser,目前没有任何额外字段。

第一次出现错误时听到:

ErrorExceptionPage

我已经搜索了答案,并遇到了连接池等主题。

我的问题是,当谈到合并时,我不确切知道EF Core已经为我做了什么。

我是否需要在每次使用后使用“using-blocks”处理UserManager和RoleManager,或者是否有完全不同的解决方案?

0 个答案:

没有答案