本文介绍了在数据层中为实体添加.NET Identity ApplicationUser的关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Identity来构建.NET MVC应用程序以进行用户登录.该应用程序具有四个层.

I'm building an .NET MVC application with Identity for user login. The application has four Layers.

  • Web/UI层,已引用我的域和服务层
  • 域层,没有引用
  • 服务层,已引用我的数据和域层
  • 数据层,已引用我的域层

我希望我的 AppUser 类与我在数据层 Company 中的一个实体有关联.

I want my AppUser class to have a reltionship to one of my entities in my data layer, Company.

AppUser 类驻留在我的域层中,并且是从 IdentityUser 继承的.我将 AppUser 类放在域层中的原因是,因为我需要从 IdentityConfig 需要该类的Web/UI层访问它.

The AppUser class is residing in my domain layer and it is inheriting from IdentityUser. The reason i placed my AppUser class in my domain layer is beacuse i need to have access to it from my Web/UI layer where the IdentityConfig needs the class.

但是当我现在想在我的数据层中向实体添加关系时,事情就变得棘手了.

But when i now want to add a relationhip to an entity in my data layer things got tricky for me.

AppUser类:

using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Security.Claims;
using System.Threading.Tasks;

namespace ITKA.Domain.Classes
{
    public class AppUser : IdentityUser
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string ContactNumber { get; set; }
        public int CompanyId { get; set; }
        public Company Company { get; set; }

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<AppUser> manager)
        {
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            return userIdentity;
        }

        public void Dispose()
        {

        }
    }
}

公司类别:

using ITKA.Data.Interfaces;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace ITKA.Data.Entities
{
    [Table("CompanyTbl")]
    public class Company : IEntity
    {
        [Key]
        public int Id { get; set; }

        [StringLength(100)]
        public string CompanyName { get; set; }

        public virtual ICollection<InventoryItem> InventoryItems { get; set; }
    }
}

IdentityConfig类的外观

using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security;
using ITKA.Domain.Classes;
using ITKA.Domain.Interfaces;

namespace ITKA.Web
{
    public class AppUserManager : UserManager<AppUser>
    {
        public AppUserManager(IUserStore<AppUser> userStore)
            : base(userStore)
        {
        }

        public static AppUserManager Create(IdentityFactoryOptions<AppUserManager> options, IOwinContext context) 
        {
            var userStore = new UserStore<AppUser>((IdentityDbContext<AppUser>)context.Get<IITKAContext>());
            var manager = new AppUserManager(userStore);

            manager.UserValidator = new UserValidator<AppUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };

            manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 8,
                RequireNonLetterOrDigit = false,
                RequireDigit = true,
                RequireLowercase = true,
                RequireUppercase = true
            };

            manager.UserLockoutEnabledByDefault = false;
            manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
            manager.MaxFailedAccessAttemptsBeforeLockout = 5;

            return manager;
        }
    }

    public class AppSignInManager : SignInManager<AppUser, string>
    {
        public AppSignInManager(AppUserManager userManager,
            IAuthenticationManager authManager)
            : base(userManager, authManager) { }

        public static AppSignInManager Create
            (IdentityFactoryOptions<AppSignInManager> options, IOwinContext context)
        {
            return new AppSignInManager(context.Get<AppUserManager>(),
                context.Authentication);
        }
    }

    public class AppRoleManager : RoleManager<IdentityRole>
    {
        public AppRoleManager(RoleStore<IdentityRole> roleStore)
            : base(roleStore) { }

        public static AppRoleManager Create(IOwinContext context)
        {
            var roleStore = new RoleStore<IdentityRole>
                ((IdentityDbContext<AppUser>)context.Get<IITKAContext>());

            return new AppRoleManager(roleStore);
        }
    }
}

我不知道如何在我的数据层中放置 AppUser 类,以便 IdentityConfig 能够到达"该类,因为这些层没有参考彼此.

I dont know how to be able to place the AppUser class in my data layer so that IdentityConfig can be able to "reach" it since those layers has no reference to each other.

我试图将我的 AppUser 类移动到数据层,并使其使用添加到我的域层 IAppUser 的界面.我更改了 IdentityConfig 以使用我的界面而不是我的课堂,但这给了我很多squiggliez.

I tried to move my AppUser class to my data layer and made it use an interface i added to my domain layer, IAppUser. I changed IdentityConfig to use my interface instead of my class but it gave me alot of squiggliez.

我遇到的第一个问题是 IAppUser IUser 之间没有隐式转换,所以我使我的 IAppUser 接口从 IUser ,它解决了 IdentityConfig 类中的一些问题.

First issue i ran into was that there where no implicit conversion between IAppUser and IUser, so i made my IAppUser interface inherit from IUser and it solved some problems in the IdentityConfig class.

但是在某些地方,它仍然抱怨 IAppUser 和类 IdentityUser 之间没有隐式转换.我无法使我的界面从类继承,所以实验结束了.

But in some places it still complained that there is no implicit conversion between IAppUser and the class IdentityUser. I cant make my interface inherit from a class so there that experiment ended.

我不知道是否可以通过域层中的接口向我的数据层中的实体添加与 AppUser 类的关系?感觉这对我来说是行不通的,因为我认为EF需要隐式地知道它与之建立关系的类/实体.而且由于许多不同的类kan是从接口继承的,所以在我看来这是不可能的.我错了吗?

I dont know if there is a way to add a relationship to my AppUser class to an entity that is in my data layer through an interface in my domain layer maybe? This feels like it wouldn't work to me because i think that EF needs to know implicitly what class/entity it makes a relationship to. And since many diffrent classes kan inherit from an interface this feels impossible to me. Am i wrong?

或者我可以在我的 AppUser 类中具有带接口的属性,并且EF可以创建关系吗?如果我的 Company 类将使用名为 ICompany 的接口,并且我的 AppUser 类具有如下属性:

Or could i have in my AppUser class a property with an interface and EF would create an relationship? If my Company class would use an interface named ICompany and my AppUser class have a property like:

public ICompany Company { get; set; }

会与公司建立关系吗?

IdentityConfig 需要我的DbContext类(也驻留在我的数据层中)时,我遇到了麻烦,但是我可以通过使用域层中的接口来解决该问题.

I had trouble when IdentityConfig needed my DbContext class that also resides in my data layer but that problem i was able to solve by using an interface in my domain layer.

我真的被困在这里,我不知道如何解决这个问题.感谢您的帮助.

Im really stuck here and i dont know how to solve this problem. I am thankful for any help.

推荐答案

如果您将数据层添加到域层引用中,那么我首先发现循环引用存在问题.您不希望Domain和Data互相引用.

I see you have a problem with circular references at first if you add data layer to your domain layer references. You don't want Domain and Data to reference eachother.

删除此引用:

并在您的域层中引用数据层:

And reference the Data Layer in your Domain Layer:

现在应该看起来像这样.

It should now look something like this.

Web -> Domain  -> Data

    -> Service -> Data
               -> Domain
  1. Web 图层引用 Domain Service 图层.
  2. 引用了数据层.
  3. 服务层引用了数据
  1. Web layer references Domain and Service layers.
  2. Domain references the Data layer.
  3. Service layer references the Data and Domain layers

请注意,数据层是最低的参考,因此数据层将没有具有任何参考.

Please note Data Layer is the lowest reference, so the Data Layer will not have any references.

AppUser类保留在域层中.

由于第2点,域"层引用了数据"层,因此您现在可以使用Company实体.

Because of point #2, Domain layer references the Data layer, you can now use the Company entity.

AppUser.cs

using ITKA.Data.Entities;
//or just use ITKA.Data.Entities.Company

namespace ITKA.Domain.Classes 
{
    public class AppUser : IdentityUser
    {
        ....
        public virtual Company Company { get; set; }
        ....
    }
}

现在进入Web层-由于第1点,Web引用了Domain层,从而允许它访问AppUser

Now for the Web layer - because of point #1, Web references the Domain layer, allowing it to access the AppUser class

IdentityConfig.cs

using ITKA.Domain.Classes;
//or just use ITKA.Domain.Classes.AppUser;

namespace ITKA.Web 
{
    public class AppUserManager : UserManager<AppUser>
    {
        ....
        public virtual Company Company { get; set; }
        ....
    }
}

您最喜欢还必须将IdentityDbContext保留在域层中,并将实体DbContext保留在数据层中.两者仍然可以指向相同的连接字符串.

You most like also have to keep your IdentityDbContext in the domain layer as well, and keep entity DbContext in data layer. Both can still point to the same connection string though.

我希望这会有所帮助.

这篇关于在数据层中为实体添加.NET Identity ApplicationUser的关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 10:40