Record: How to use ASP.NET Core and EnityFramework Core to separate database operations and database entities

Recap:

  There is an existing website framework, including a main project WebApp, a scaffold project A that includes the IIdentityUser interface. AuthenticationService, the service used to handle user authentication, is located in namespace B. Entity User for saving data: IIdentityUser Location item C. The relationship between projects is that B and C depend on project A.

 

demand:

  Now there is a new project D, in this project there is a DUser: IIdentityUser. How to deal with it is the most elegant way to save users to DUser without adding references and modifying project B.

 

Practical examples:

  In ASP.NET CORE, there is something called IdentityServer. There is this thing in it. He wrote code similar to IdentityServerBuilder.AddService <TUser, TRole> (), how to achieve it?

 

solution:

  1. Create a new generic class (this class can be marked as internal, and the external does not need to understand or access):

public class UserContext<TUser>
        where TUser : class, IIdentityUser, new ()
    {
        public YourContext dbContext;
        public UserContext(YourContext ctx) => dbContext = ctx;

        public DbSet<TUser> Users
        {
            get
            {
                return dbContext.Set<TUser>();
            }
        }

        public void SaveChanges()
        {
            dbContext.SaveChanges();
        }
    }

  2. Create a new service for operation (note that all required operations are written in this, and this interface will be exposed in the future)

public class UserService<TUser> : IUserService
        where TUser: class, IIdentityUser, new()
    {
        private UserContext<TUser> dbContext;
        public UserService(YourContext ctx, IServiceProvider provider)
        {
            dbContext = new PermissionContext<TUser>(ctx.DbContext);
        }
     
   public TUser GetUserById(Guid id)
   {
      return dbContext.Users.FirstOrDefault(e => e.ID == id);
   }
    }

  

  3. Add a syringe

    public static class AuthenticationInject
    {
        public static IServiceCollection AddAuthenticationContext<TUser>(this IServiceCollection services)
            where TUser: IIdentityUser
        {
            var serviceType = typeof(UserService<>).MakeGenericType(typeof(TUser));
            services.AddSingleton(typeof(IUserService), serviceType );

            return services;
        }
    }

  Technical point: Use the MakeGenericType method to dynamically load generic class instances. If the type is UserService <TUser, TRole>, it is written as typeof (UserService <,>). MakeGenericType (typeof (T1), typeof (T2))

  So far, we have split the type name of the generic class into the variable. Then you can play 10,000 patterns.

  4. In WebApp, inject related variables

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddAuthenticationContext<DUser>();
        }

  

  Analyze dependencies:

  Execution project WebApp depends on A, B, D, B and D projects only depend on A. Even more, it can be decoupled again. Change the function AddAuthenticationContext from the generic function to AddAuthenticationContext (Type userType), and you can go further and change it to AddAuthenticationContext (string type) to get the type through reflection and configuration, so as to decouple A and D projects.

  Expandability:

  In the future, there will be new projects E, EUser. You only need to disassociate D and A, and then associate E and A. Just modify the AddAuthenticationContext function to meet the requirements. Of course, if you want to be in a mood, you can even engage in an auto-discovery code (such as this in my project, which automatically analyzes the IIdentityUser object and then attaches it to the Context. In order to ensure that it can be correctly attached when there are multiple implementations, I do An Attribute is used to mark which User to use for this project). Even if you are in a mood, you can make it configurable. Anyway, you can put EF Core in 10,000 poses.

Guess you like

Origin www.cnblogs.com/Pray4U/p/12732296.html