Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs源代码
2016-09-09 10:47
411 查看
// Copyright (c) Microsoft Corporation, Inc. All rights reserved. // Licensed under the MIT License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Common; using System.Data.Entity; using System.Data.Entity.Core.Objects; 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 IdentityDbContext that uses the default entity types for ASP.NET Identity Users, Roles, Claims, Logins. /// Use this overload to add your own 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> /// Constructs a new context instance using conventions to create the name of /// the database to which a connection will be made, and initializes it from /// the given model. The by-convention name is the full name (namespace + class /// name) of the derived context class. See the class remarks for how this is /// used to create a connection. /// </summary> /// <param name="model">The model that will back this context.</param> public IdentityDbContext(DbCompiledModel model) : base(model) { } /// <summary> /// Constructs a new context instance using the existing connection to connect /// to a database. 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="contextOwnsConnection">If set to true the connection is disposed when the context is disposed, otherwise /// the caller must dispose the connection. /// </param> public IdentityDbContext(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection) { } /// <summary> /// Constructs a new context instance using the given string as the name or connection /// string for the database to which a connection will be made, and initializes /// it from the given model. See the class remarks for how this is used to create /// a connection. /// </summary> /// <param name="nameOrConnectionString">Either the database name or a connection string.</param> /// <param name="model">The model that will back this context.</param> public IdentityDbContext(string nameOrConnectionString, DbCompiledModel model) : base(nameOrConnectionString, model) { } } /// <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) { } /// <summary> /// Constructs a new context instance using conventions to create the name of /// the database to which a connection will be made, and initializes it from /// the given model. The by-convention name is the full name (namespace + class /// name) of the derived context class. See the class remarks for how this is /// used to create a connection. /// </summary> /// <param name="model">The model that will back this context.</param> public IdentityDbContext(DbCompiledModel model) : base(model) { } /// <summary> /// Constructs a new context instance using the existing connection to connect /// to a database. The connection will not be disposed when the context is disposed /// if conte 4000 xtOwnsConnection is false. /// </summary> /// <param name="existingConnection">An existing connection to use for the new context.</param> /// <param name="contextOwnsConnection">If set to true the connection is disposed when the context is disposed, otherwise /// the caller must dispose the connection. /// </param> public IdentityDbContext(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection) { } /// <summary> /// Constructs a new context instance using the given string as the name or connection /// string for the database to which a connection will be made, and initializes /// it from the given model. See the class remarks for how this is used to create /// a connection. /// </summary> /// <param name="nameOrConnectionString">Either the database name or a connection string.</param> /// <param name="model">The model that will back this context.</param> public IdentityDbContext(string nameOrConnectionString, DbCompiledModel model) : base(nameOrConnectionString, model) { } 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(0)); } } } // Make sure that we find all the expected columns return columns.All(tableColumns.Contains); } } /// <summary> /// Generic IdentityDbContext base that can be customized with entity types that extend from the base IdentityUserXXX types. /// </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> /// Constructs a new context instance using conventions to create the name of /// the database to which a connection will be made, and initializes it from /// the given model. The by-convention name is the full name (namespace + class /// name) of the derived context class. See the class remarks for how this is /// used to create a connection. /// </summary> /// <param name="model">The model that will back this context.</param> public IdentityDbContext(DbCompiledModel model) : base(model) { } /// <summary> /// Constructs a new context instance using the existing connection to connect /// to a database. 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="contextOwnsConnection">If set to true the connection is disposed when the context is disposed, otherwise /// the caller must dispose the connection. /// </param> public IdentityDbContext(DbConnection existingConnection, bool contextOwnsConnection) : base(existingConnection, contextOwnsConnection) { } /// <summary> /// Constructs a new context instance using the given string as the name or connection /// string for the database to which a connection will be made, and initializes /// it from the given model. See the class remarks for how this is used to create /// a connection. /// </summary> /// <param name="nameOrConnectionString">Either the database name or a connection string.</param> /// <param name="model">The model that will back this context.</param> public IdentityDbContext(string nameOrConnectionString, DbCompiledModel model) : base(nameOrConnectionString, model) { } /// <summary> /// IDbSet of Users /// </summary> public virtual IDbSet<TUser> Users { get; set; } /// <summary> /// IDbSet 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(256) .HasColumnAnnotation("Index", new IndexAnnotation(new IndexAttribute("UserNameIndex") { IsUnique = true })); // CONSIDER: u.Email is Required if set on options? user.Property(u => u.Email).HasMaxLength(256); 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(256) .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); } } }
想定制.net entityframework 验证。网上找了半天没找到方法,找到如上代码,保存以备参考研究。
以上源码出自:
https://www.symbolsource.org/MyGet/Metadata/aspnetwebstacknightly/Project/Microsoft.AspNet.Identity.EntityFramework/2.3.0-rtm-160831/Release/Default/Microsoft.AspNet.Identity.EntityFramework/Microsoft.AspNet.Identity.EntityFramework/IdentityDbContext.cs?ImageName=Microsoft.AspNet.Identity.EntityFramework
相关文章推荐
- 零代码保存窗口运行状态
- 不改一行代码定位线上性能问题
- Delphi 程序员代码编写标准指南 (五)
- Delphi 程序员代码编写标准指南 (四)
- Delphi 程序员代码编写标准指南 (二)
- Delphi 程序员代码编写标准指南
- 如何在VC中加入汇编代码?
- 如何让VC只输出汇编代码?
- 关于Basic程序解释器及编译原理的简单化(1)---Basic器的语法分析及主要代码
- 一步一步开始Web Service (有代码和图) (上)
- 一步一步开始Web Service (有代码和图) (下)
- 提高Java代码可重用性的三个措施
- Win32 API资源分配释放速查,防止代码资源泄露
- C++Builder常用代码片断
- 代码的风格
- Delphi程序员代码编写标准指南
- VB 实现大文件的分割与恢复,引用 ADODB.Stream 提供一个过程代码
- 一段精简的使用 ADODB.Stream 读写"大字段"的 VB 代码!
- VB 实现大文件的分割与恢复,引用 ADODB.Stream 提供一个过程代码
- Java代码编写的一般性指导