如何为Identity Framework设置实体框架模型以使其与现有数据库兼容? [英] How to set up the Entity Framework model for Identity Framework to work against an existing database?

查看:64
本文介绍了如何为Identity Framework设置实体框架模型以使其与现有数据库兼容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将旧网站从PHP迁移到C#MVC.我想使用Microsoft的Identity设置,因为它看起来很简洁.

I am migrating my old website from PHP to C# MVC. I want to use Microsoft's Identity set-up as it looks rather neat.

我已经使用数据库优先实体框架设置了解决方案.我有必需的表(Users,UserRoles,UserLogins,UserClaims),并设置了所有外键.

I already have my solution set up using database-first entity framework. I have the required tables (Users, UserRoles, UserLogins, UserClaims) with all of the foreign keys set up.

我研究了几种设置IdentityUser的方法,这些方法首先使用了MySqlDatabase并进行了编码,但是当我已经建立了数据库时,我不确定如何实现我的IdentityUser,包括现有的Users表.

I've looked at a few ways of setting up the IdentityUser, ones that have used MySqlDatabase and code first, but I'm not sure how to implement my IdentityUser when I already have an established database, including an existing Users table.

我希望我的IdentityUser使用已经创建的Entity Framework类来操纵Users.有没有办法让我的EF中的User模型从IdentityUser派生并匹配我现有的数据库?

I want my IdentityUser to manipulate my Users using the Entity Framework classes that I've already created. Is there a way of making my User model in EF to derive from IdentityUser and match my existing database?

我特别努力的一件事是我的数据库没有使用string值作为主键,而是使用了自动递增的int.

One thing specifically that I am struggling with is that my database doesn't use a string value as the primary key, it uses an auto-incrementing int.

目前,我有以下课程:

// Copyright (c) KriaSoft, LLC.  All rights reserved.  See LICENSE.txt in the project root for license information.

namespace KriaSoft.AspNet.Identity.EntityFramework
{
    using Microsoft.AspNet.Identity;
    using System;

    public partial class IdentityUser : IUser<int>
    {
        /// <summary>
        /// Default constructor 
        /// </summary>
        public IdentityUser()
        {
            Id = Guid.NewGuid().ToString();
        }

        /// <summary>
        /// Constructor that takes user name as argument
        /// </summary>
        /// <param name="userName"></param>
        public IdentityUser(string userName)
            : this()
        {
            UserName = userName;
        }

        /// <summary>
        /// User ID
        /// </summary>
        public string Id { get; set; }

        /// <summary>
        /// User's name
        /// </summary>
        public string UserName { get; set; }

        /// <summary>
        ///     Email
        /// </summary>
        public virtual string Email { get; set; }

        /// <summary>
        ///     True if the email is confirmed, default is false
        /// </summary>
        public virtual bool EmailConfirmed { get; set; }

        /// <summary>
        ///     The salted/hashed form of the user password
        /// </summary>
        public virtual string PasswordHash { get; set; }

        /// <summary>
        ///     A random value that should change whenever a users credentials have changed (password changed, login removed)
        /// </summary>
        public virtual string SecurityStamp { get; set; }

        /// <summary>
        ///     PhoneNumber for the user
        /// </summary>
        public virtual string PhoneNumber { get; set; }

        /// <summary>
        ///     True if the phone number is confirmed, default is false
        /// </summary>
        public virtual bool PhoneNumberConfirmed { get; set; }

        /// <summary>
        ///     Is two factor enabled for the user
        /// </summary>
        public virtual bool TwoFactorEnabled { get; set; }

        /// <summary>
        ///     DateTime in UTC when lockout ends, any time in the past is considered not locked out.
        /// </summary>
        public virtual DateTime? LockoutEndDateUtc { get; set; }

        /// <summary>
        ///     Is lockout enabled for this user
        /// </summary>
        public virtual bool LockoutEnabled { get; set; }

        /// <summary>
        ///     Used to record failures for the purposes of lockout
        /// </summary>
        public virtual int AccessFailedCount { get; set; }
    }
}

当然,我的Entity Framework数据库上下文中的Users实体已经具有所有这些属性,因此在其中以及我的上下文中指定它们似乎毫无意义……我真的不确定: (.

Of course, my Users entity within my Entity Framework database context already has all of these properties, so it seems a bit pointless having them specified in there as well as my context... I'm really not sure :(.

我想我的问题是:如何将现有的实体框架User模型(首先是数据库)用作Asp.net身份的IdentityUser?

I guess my question is: How do use my existing entity framework User model (database first) as my IdentityUser for Asp.net Identity?

推荐答案

我现在对此更加熟悉.

最先通过代码或数据库优先运行的方法是更改​​现有数据库,使其至少具有ASP使用的最小数据库架构(表,列和外键) .NET身份框架.

The most straightforward way to get this to work either code-first or database-first, is to change your existing database so that it has at least the minimum database schema (tables, columns and foreign keys) that is used by ASP.NET Identity Framework.

您可以在下图中看到最小架构:

You can see the minimum schema in the image below:

尽管它没有列类型,但仍然很有用.您可以从此页面上列出的 SQL数据库项目模板中获取精确的架构.

Although it doesn't have column types, it's still useful to see. You can get the precise schema from the SQL Database Project template listed on this page.

我敢肯定,可以通过在代码内(代码优先)或使用EF工具(数据库优先)创建某种类型的映射来避免使现有数据库遵循此架构,列名改为您的代码中的另一个名字...但是我还没有尝试过.

I'm sure it's possible to avoid having to make your existing database adhere to this schema by creating some kind of mappings either within your code (code-first) or using the EF tools (database-first) to map from the column name to another name within your code... but I haven't tried it.

除了User表之外,我从头开始创建了大多数表,在这里我将原来的Username列更改为名称UserName(大小写更正)以匹配并添加了其他不包含的列已经存在.

I created most of the tables from scratch, other than the User table, where I changed my original Username column to the name UserName (case correction) to match and added the additional columns that didn't already exist.

一旦有了数据库,并且知道该架构是正确的,那么您可能要考虑使用Visual Studio的reverse-engineer code first功能为您架设EF类.这样,您的新EF类将与您的表布局完全匹配.否则,您必须自己使用所有映射对所有模型进行编码.

Once you have the database in place and you know that the schema is correct, then you may want to consider using the reverse-engineer code first feature of Visual Studio to scaffold your EF classes for you. This way your new EF classes will match your table layouts precisely. Otherwise, you'll have to code all of your models yourself with all of the mappings.

一旦有了EF类,就应该使它们从Identity Framework的不同类继承.当您首先以代码的形式进行操作时,可以将继承添加到EF类中,而不必担心它们会被覆盖(与首先使用数据库不同).

Once you have the EF classes in place, you should make them inherit from different classes from Identity Framework. As you're doing this as code first, you can add the inheritance to the EF classes without any fear of them being overwritten (unlike with database first).

public class User : IdentityUser<int, UserLogin, UserRole, UserClaim>
{
    // Any additional columns from your existing users table will appear here.
}

public class Role : IdentityRole<int, UserRole>
{
}

public class UserClaim : IdentityUserClaim<int>
{
}

public class UserLogin : IdentityUserLogin<int>
{
}

public class UserRole : IdentityUserRole<int>
{
}

注意每个中指定的int,它指定User表的主键类型.默认情况下,这是一个字符串,但是我现有数据库中的Id值是一个自动递增的int.

Notice the int specified in each, this specifies the primary key type of the User table. This is, by default, a string, but my Id value in my existing database is an int that auto-increments.

当您首先使用EF数据库时,您没有奢侈地将Identity Framework类的继承直接添加到自动生成的类中.这是因为每次您使用Entity Framework Visual Studio工具对模型进行更改时,它们都会被覆盖.

When you're using EF database-first, you don't have the luxury of adding the inheritance of the Identity Framework classes directly to the automatically generated classes. This is because they are overwritten every time you make a change to the model using the Entity Framework Visual Studio tools.

但是,创建的类都是partial类,它们是自动生成的,因此可以通过创建一个新的文件来实现,该文件的部分类的定义不会被覆盖.它们必须在相同的名称空间中,并且名称完全相同.

However, the classes that are created are auto generated are all partial classes, so it can be achieved by creating a new file with the definition of the partial classes that won't get overwritten. They must be in the same namespace and exactly the same name.

例如,这可能是EF生成的类:

So for example, this might be the class generated by EF:

namespace Dal
{
    public partial class User
    {
        // This class is auto generated by using EF database-first
        // We can't edit this class to add the inheritance,
        // because it will be overwritten every time
        // we update our model using the database-first tools
    }
}

这是我们可以创建的模型,用于将继承添加到:

And this is the model that we can create to add our inheritance to:

// same namespace as existing class
namespace Dal
{
    // Same name as existing class
    public partial class User : IdentityUser<int, UserLogin, UserRole, UserClaim>
    {
        // This can probably be left blank
    }
}

因此,您将对ASP.NET Identity Framework所需的每个类执行此操作:

So you would do this for each of the classes required by ASP.NET Identity Framework:

public partial class User : IdentityUser<int, UserLogin, UserRole, UserClaim>
{
    // Any additional columns from your existing users table will appear here.
}

public partial class Role : IdentityRole<int, UserRole>
{
}

public partial class UserClaim : IdentityUserClaim<int>
{
}

public partial class UserLogin : IdentityUserLogin<int>
{
}

public partial class UserRole : IdentityUserRole<int>
{
}

这篇关于如何为Identity Framework设置实体框架模型以使其与现有数据库兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆