using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Infrastructure.Annotations;
using System.Data.Entity.Validation;
using System.Data.SqlClient;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq; namespace Microsoft.AspNet.Identity.EntityFramework
{
/// <summary>
/// Default db context that uses the default entity types
/// </summary>
public class IdentityDbContext :
IdentityDbContext<IdentityUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
{
/// <summary>
/// Default constructor which uses the DefaultConnection
/// </summary>
public IdentityDbContext()
: this("DefaultConnection")
{
} /// <summary>
/// Constructor which takes the connection string to use
/// </summary>
/// <param name="nameOrConnectionString"></param>
public IdentityDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
} /// <summary>
/// Constructs a new context instance using the existing connection to connect to a database, and initializes it from
/// the given model. The connection will not be disposed when the context is disposed if contextOwnsConnection is
/// false.
/// </summary>
/// <param name="existingConnection">An existing connection to use for the new context.</param>
/// <param name="model">The model that will back this context.</param>
/// <param name="contextOwnsConnection">
/// Constructs a new context instance using the existing connection to connect to a
/// database, and initializes it from the given model. The connection will not be disposed when the context is
/// disposed if contextOwnsConnection is false.
/// </param>
public IdentityDbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)
: base(existingConnection, model, contextOwnsConnection)
{
}
} /// <summary>
/// DbContext which uses a custom user entity with a string primary key
/// </summary>
/// <typeparam name="TUser"></typeparam>
public class IdentityDbContext<TUser> :
IdentityDbContext<TUser, IdentityRole, string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
where TUser : IdentityUser
{
/// <summary>
/// Default constructor which uses the DefaultConnection
/// </summary>
public IdentityDbContext()
: this("DefaultConnection")
{
} /// <summary>
/// Constructor which takes the connection string to use
/// </summary>
/// <param name="nameOrConnectionString"></param>
public IdentityDbContext(string nameOrConnectionString)
: this(nameOrConnectionString, true)
{
} /// <summary>
/// Constructor which takes the connection string to use
/// </summary>
/// <param name="nameOrConnectionString"></param>
/// <param name="throwIfV1Schema">Will throw an exception if the schema matches that of Identity 1.0.0</param>
public IdentityDbContext(string nameOrConnectionString, bool throwIfV1Schema)
: base(nameOrConnectionString)
{
if (throwIfV1Schema && IsIdentityV1Schema(this))
{
throw new InvalidOperationException(IdentityResources.IdentityV1SchemaError);
}
} /// <summary>
/// Constructs a new context instance using the existing connection to connect to a database, and initializes it from
/// the given model. The connection will not be disposed when the context is disposed if contextOwnsConnection is
/// false.
/// </summary>
/// <param name="existingConnection">An existing connection to use for the new context.</param>
/// <param name="model">The model that will back this context.</param>
/// <param name="contextOwnsConnection">
/// Constructs a new context instance using the existing connection to connect to a
/// database, and initializes it from the given model. The connection will not be disposed when the context is
/// disposed if contextOwnsConnection is false.
/// </param>
public IdentityDbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)
: base(existingConnection, model, contextOwnsConnection)
{
} internal static bool IsIdentityV1Schema(DbContext db)
{
var originalConnection = db.Database.Connection as SqlConnection;
// Give up and assume its ok if its not a sql connection
if (originalConnection == null)
{
return false;
} if (db.Database.Exists())
{
using (var tempConnection = new SqlConnection(originalConnection.ConnectionString))
{
tempConnection.Open();
return
VerifyColumns(tempConnection, "AspNetUsers", "Id", "UserName", "PasswordHash", "SecurityStamp",
"Discriminator") &&
VerifyColumns(tempConnection, "AspNetRoles", "Id", "Name") &&
VerifyColumns(tempConnection, "AspNetUserRoles", "UserId", "RoleId") &&
VerifyColumns(tempConnection, "AspNetUserClaims", "Id", "ClaimType", "ClaimValue", "User_Id") &&
VerifyColumns(tempConnection, "AspNetUserLogins", "UserId", "ProviderKey", "LoginProvider");
}
} return false;
} [SuppressMessage("Microsoft.Security", "CA2100:Review SQL queries for security vulnerabilities",
Justification = "Reviewed")]
internal static bool VerifyColumns(SqlConnection conn, string table, params string[] columns)
{
var tableColumns = new List<string>();
using (
var command =
new SqlCommand("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=@Table", conn))
{
command.Parameters.Add(new SqlParameter("Table", table));
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
// Add all the columns from the table
tableColumns.Add(reader.GetString());
}
}
}
// Make sure that we find all the expected columns
return columns.All(tableColumns.Contains);
}
} /// <summary>
/// IdentityDbContext of IdentityUsers
/// </summary>
/// <typeparam name="TUser"></typeparam>
/// <typeparam name="TRole"></typeparam>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TUserLogin"></typeparam>
/// <typeparam name="TUserRole"></typeparam>
/// <typeparam name="TUserClaim"></typeparam>
public class IdentityDbContext<TUser, TRole, TKey, TUserLogin, TUserRole, TUserClaim> : DbContext
where TUser : IdentityUser<TKey, TUserLogin, TUserRole, TUserClaim>
where TRole : IdentityRole<TKey, TUserRole>
where TUserLogin : IdentityUserLogin<TKey>
where TUserRole : IdentityUserRole<TKey>
where TUserClaim : IdentityUserClaim<TKey>
{
/// <summary>
/// Default constructor which uses the "DefaultConnection" connectionString
/// </summary>
public IdentityDbContext()
: this("DefaultConnection")
{
} /// <summary>
/// Constructor which takes the connection string to use
/// </summary>
/// <param name="nameOrConnectionString"></param>
public IdentityDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
} /// <summary>
/// Constructs a new context instance using the existing connection to connect to a database, and initializes it from
/// the given model. The connection will not be disposed when the context is disposed if contextOwnsConnection is
/// false.
/// </summary>
/// <param name="existingConnection">An existing connection to use for the new context.</param>
/// <param name="model">The model that will back this context.</param>
/// <param name="contextOwnsConnection">
/// Constructs a new context instance using the existing connection to connect to a
/// database, and initializes it from the given model. The connection will not be disposed when the context is
/// disposed if contextOwnsConnection is false.
/// </param>
public IdentityDbContext(DbConnection existingConnection, DbCompiledModel model, bool contextOwnsConnection)
: base(existingConnection, model, contextOwnsConnection)
{
} /// <summary>
/// EntitySet of Users
/// </summary>
public virtual IDbSet<TUser> Users { get; set; } /// <summary>
/// EntitySet of Roles
/// </summary>
public virtual IDbSet<TRole> Roles { get; set; } /// <summary>
/// If true validates that emails are unique
/// </summary>
public bool RequireUniqueEmail { get; set; } /// <summary>
/// Maps table names, and sets up relationships between the various user entities
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (modelBuilder == null)
{
throw new ArgumentNullException("modelBuilder");
} // Needed to ensure subclasses share the same table
var user = modelBuilder.Entity<TUser>()
.ToTable("AspNetUsers");
user.HasMany(u => u.Roles).WithRequired().HasForeignKey(ur => ur.UserId);
user.HasMany(u => u.Claims).WithRequired().HasForeignKey(uc => uc.UserId);
user.HasMany(u => u.Logins).WithRequired().HasForeignKey(ul => ul.UserId);
user.Property(u => u.UserName)
.IsRequired()
.HasMaxLength()
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UserNameIndex") { IsUnique = true })); // CONSIDER: u.Email is Required if set on options?
user.Property(u => u.Email).HasMaxLength(); modelBuilder.Entity<TUserRole>()
.HasKey(r => new { r.UserId, r.RoleId })
.ToTable("AspNetUserRoles"); modelBuilder.Entity<TUserLogin>()
.HasKey(l => new { l.LoginProvider, l.ProviderKey, l.UserId })
.ToTable("AspNetUserLogins"); modelBuilder.Entity<TUserClaim>()
.ToTable("AspNetUserClaims"); var role = modelBuilder.Entity<TRole>()
.ToTable("AspNetRoles");
role.Property(r => r.Name)
.IsRequired()
.HasMaxLength()
.HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("RoleNameIndex") { IsUnique = true }));
role.HasMany(r => r.Users).WithRequired().HasForeignKey(ur => ur.RoleId);
} /// <summary>
/// Validates that UserNames are unique and case insenstive
/// </summary>
/// <param name="entityEntry"></param>
/// <param name="items"></param>
/// <returns></returns>
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry,
IDictionary<object, object> items)
{
if (entityEntry != null && entityEntry.State == EntityState.Added)
{
var errors = new List<DbValidationError>();
var user = entityEntry.Entity as TUser;
//check for uniqueness of user name and email
if (user != null)
{
if (Users.Any(u => String.Equals(u.UserName, user.UserName)))
{
errors.Add(new DbValidationError("User",
String.Format(CultureInfo.CurrentCulture, IdentityResources.DuplicateUserName, user.UserName)));
}
if (RequireUniqueEmail && Users.Any(u => String.Equals(u.Email, user.Email)))
{
errors.Add(new DbValidationError("User",
String.Format(CultureInfo.CurrentCulture, IdentityResources.DuplicateEmail, user.Email)));
}
}
else
{
var role = entityEntry.Entity as TRole;
//check for uniqueness of role name
if (role != null && Roles.Any(r => String.Equals(r.Name, role.Name)))
{
errors.Add(new DbValidationError("Role",
String.Format(CultureInfo.CurrentCulture, IdentityResources.RoleAlreadyExists, role.Name)));
}
}
if (errors.Any())
{
return new DbEntityValidationResult(entityEntry, errors);
}
}
return base.ValidateEntity(entityEntry, items);
}
}
}

上面的代码出自:

https://www.symbolsource.org/MyGet/Metadata/aspnetwebstacknightly/Project/Microsoft.AspNet.Identity.EntityFramework/2.0.0-rtm-140221/Release/Default/Microsoft.AspNet.Identity.EntityFramework/Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs?ImageName=Microsoft.AspNet.Identity.EntityFramework

想查看Microsoft.AspNet.Identity.EntityFramework.dll中IdentityDbContext的源码,却发现Github上Identity的代码和实际调用的dll里面的结构不一致。

找到如上代码,留文备用。

Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs的更多相关文章

  1. Asp.net Identity 系列之 怎样修改Microsoft.AspNet.Identity.EntityFramework.IdentityUser 的 Id 字段的数据类型

    这篇博客我们来学习如何将AspNetUsers 表的Id 字段 的类型由nvarchar(128) 改为Int 并且子增长 1.为什么要修改 如果你运行过 Asp.net mvc 示例项目,你好会发现 ...

  2. 从Microsoft.AspNet.Identity看微软推荐的一种MVC的分层架构

    Microsoft.AspNet.Identity简介 Microsoft.AspNet.Identity是微软在MVC 5.0中新引入的一种membership框架,和之前ASP.NET传统的mem ...

  3. Microsoft.AspNet.Identity 自定义使用现有的表—登录实现

    Microsoft.AspNet.Identity是微软新引入的一种membership框架,也是微软Owin标准的一个实现.Microsoft.AspNet.Identity.EntityFrame ...

  4. Microsoft.AspNet.Identity 的简单使用

    要完成一个简单的注册,登陆,至少需要实现Identity中的3个接口 IUser IUserStore<TUser> : IDisposable where TUser : IUser I ...

  5. MVC5中 在更新 Microsoft.Aspnet.Identity 后编译器错误

    环境:vs2013预览版chs,我试着创建vb.net web应用,从对话框中选择MVC和WebAPI.编译ok了.通过NuGet管理器更新了Microsoft.Aspnet.Identity.Cor ...

  6. Microsoft.AspNet.Identity 自定义使用现有的表—登录实现,aspnet.identity

    Microsoft.AspNet.Identity是微软新引入的一种membership框架,也是微软Owin标准的一个实现.Microsoft.AspNet.Identity.EntityFrame ...

  7. 跟Microsoft.AspNet.Identity学习哈希加盐法

    什么是哈希加盐法? 废话少说:对于MD5这种加密算法,同样的密码每次加密后得到的密文是一样的,所以黑客可以利用已知的密码库(彩虹库)对目标数据库密文进行对比进行攻击. 怎样解决:哈希加盐法,以下是网上 ...

  8. Microsoft.AspNet.Identity: UserID用整型数据表示, 而不是GUID

    第一篇:  这个好像不太好 http://stackoverflow.com/questions/19553424/how-to-change-type-of-id-in-microsoft-aspn ...

  9. Microsoft.AspNet.Identity 重置密码

    重置密码:先生成重置密码的Token,然后调用ResetPassword方法重置密码,密码要符合规则.. ApplicationUserManager UserManager => _userM ...

随机推荐

  1. Macos mysql 8.0.11 添加配置文件

    mac 安装mysql 后,没有配置文件,如果需要添加配置文件,需要在/etc 目录下面添加 my.cnf 文件. 添加方法 打开文件命令:sudo vi  /etc/my.cnf 文件添加内容: [ ...

  2. js关闭当前页面和给子页面的对象赋值

    代码如下: function saveData(){ //给父页面的对象赋值 frameElement.api.opener.document.getElementById("userNam ...

  3. excel文件导入mysql

    在数据处理的过程中,常常要把windows下的excel文件导入linux下的mysql.这其中会出现一些问题. 1.首先,要在mysql中建表.命令最好存在记事本中,可以随时修改,随时执行 crea ...

  4. linux c select函数使用求解释

          代码非常easy,就是发送c语言发送http请求.但 i= read(sockfd, buf, BUFSIZE-1); 能够正常执行,  替换为i= Read(sockfd, buf, B ...

  5. jQuery Direct and delegated events 直接事件与委托事件

    ref: http://api.jquery.com/on/ 直接事件: 将事件委托直接绑定到dom元素上,当事件发生时触发handler. 委托事件:  将事件委托绑定到dom元素的外层容器上,当事 ...

  6. Android 两个界面间快速切换时,会发现有短暂黑屏

    这种问题一般是因为一个Activity启动之后在显示视图之间时间太长导致的. 1.优化方式可以通过精简layout文件.多线程处理数据载入等. 2.但是有些Activity的layout文件可能比较大 ...

  7. 基于 Promise 的 HTTP 请求客户端 axios

    基于 Promise 的 HTTP 请求客户端,可同时在浏览器和 node.js 中使用 功能特性 在浏览器中发送 XMLHttpRequests 请求 在 node.js 中发送 http请求 支持 ...

  8. Socket网络编程--Libev库学习(3)

    这一小节继续讲解各个观察器(Watcher). 上一小节已经讲解了ev_io(IO可读可写观察器),ev_stat(文件属性变化观察器),ev_signal(信号处理观察器),ev_timer(定时器 ...

  9. rabbitmq 二进制安装

    # wget -Uvh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm # ls epel-rele ...

  10. HTML5学习笔记(三):语义化和新增结构元素

    在HTML5之前,使用机器来阅读一个网页是非常困难的,我们使用不同样式的div来标记不同的内容,所以实际上机器无法得知页面的哪个部分是正文,哪个部分是标题,那么在HTML5里,针对这个问题就引入了语义 ...