在数据层

时间:2018-05-21 09:21:02

标签: c# asp.net-mvc entity-framework oop asp.net-identity

我正在使用Identity为用户登录构建.NET MVC应用程序。该应用程序有四个图层。

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

我希望我的 AppUser 课程与我的数据层中的某个实体公司有关联。

AppUser 类位于我的域层中,并且继承自 IdentityUser 。我将 AppUser 类放在我的域层中的原因是因为我需要从我的Web / UI层访问它,其中 IdentityConfig 需要该类。

但是,当我现在想要在我的数据层中为实体添加关系时,对我来说事情变得棘手。

AppUser Class,我希望它看起来:

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 能够达到&#34;因为这些层没有彼此参考。

我尝试将 AppUser 类移到我的数据层,并使用我添加到域域 IAppUser 的界面。我改变了 IdentityConfig 来使用我的界面而不是我的班级,但它给了我很多squiggliez。

我遇到的第一个问题是 IAppUser IUser 之间没有隐式转换,所以我使 IAppUser 接口继承自< strong> IUser ,它解决了 IdentityConfig 类中的一些问题。

但是在某些地方,它仍然抱怨 IAppUser 和类 IdentityUser 之间没有隐式转换。我不能让我的界面继承自一个类,所以实验结束了。

我不知道是否有办法通过我的域层中的接口将我的 AppUser 类的关系添加到我的数据层中的实体?这感觉它对我不起作用,因为我认为EF需要隐含地知道它与之建立关系的类/实体。而且由于许多不同的类可以从接口继承,这对我来说是不可能的。我错了吗?

或者我可以在 AppUser 类中使用带有接口和EF的属性创建关系吗?如果我的公司类使用名为 ICompany 的界面,而我的 AppUser 类具有以下属性:

public ICompany Company { get; set; }

会与公司建立关系吗?

IdentityConfig 需要我的DbContext类同时驻留在我的数据层中但我能够通过在我的域层中使用接口来解决这个问题时,我遇到了麻烦。

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

1 个答案:

答案 0 :(得分:1)

如果您将数据层添加到域图层引用,我发现您首先遇到循环引用问题。您不希望域和数据相互引用。

删除此引用:

  
      
  • 数据图层,引用了我的域图层
  •   

并引用域层中的数据层:

  
      
  • 域层,没有引用
  •   

现在看起来应该是这样的。

Web -> Domain  -> Data

    -> Service -> Data
               -> Domain
  1. 网络图层参考服务图层。
  2. 引用数据图层。
  3. 服务图层引用数据图层
  4. 请注意数据层是最低的参考,因此数据层将有任何参考。

    将您的AppUser课程保留在域层中。

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

    <强> 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

    <强> 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保留在数据层中。两者仍然可以指向相同的连接字符串。

    我希望这会有所帮助。