我的应用程序中有一个使用IdentityDbContext的DbContext
public class ShopDbContext : IdentityDbContext<User>, IDisposable
{
public ShopDbContext(DbContextOptions options): base(options)
{
Products = base.Set<Product>();
Categories = base.Set<Category>();
Shops = base.Set<Shop>();
Properties = base.Set<Property>();
Orders = base.Set<Order>();
OrderItems = base.Set<OrderItem>();
Customers = base.Set<Customer>();
Carts = base.Set<Cart>();
CartItems = base.Set<CartItem>();
UserShops = base.Set<UserShop>();
Images = base.Set<Image>();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Use singular table names
modelBuilder.ApplyConfiguration<Product>(new ProductConfiguration());
modelBuilder.ApplyConfiguration<Category>(new CategoryConfiguration());
modelBuilder.ApplyConfiguration<Shop>(new ShopConfiguration());
modelBuilder.ApplyConfiguration<Property>(new PropertyConfiguration());
modelBuilder.ApplyConfiguration<Order>(new OrderConfiguration());
modelBuilder.ApplyConfiguration<OrderItem>(new OrderItemConfiguration());
modelBuilder.ApplyConfiguration<Customer>(new CustomerConfiguration());
modelBuilder.ApplyConfiguration<Cart>(new CartConfiguration());
modelBuilder.ApplyConfiguration<CartItem>(new CartItemConfiguration());
modelBuilder.ApplyConfiguration<UserShop>(new UserShopConfiguration());
modelBuilder.ApplyConfiguration<Image>(new ImageConfiguration());
}
public DbSet<Shop> Shops { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Property> Properties { get; set; }
public DbSet<Order> Orders { get; set; }
public DbSet<OrderItem> OrderItems { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Cart> Carts { get; set; }
public DbSet<CartItem> CartItems { get; set; }
public DbSet<UserShop> UserShops { get; set; }
public DbSet<Image> Images { get; set; }
}
这是我的用户模型:
public class User : IdentityUser
{
public string Name { get; set; }
public string LastName { get; set; }
public string MobilePhone { get; set; }
public string Address { get; set; }
public Guid ImageId { get; set; }
public Guid ShopId { get; set; }
public DateTime LastActive { get; set; }
public List<UserShop> UserShopList { get; set; }
public bool HasImage()
{
return Guid.Empty != ImageId;
}
}
启动代码如下:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public IServiceProvider ServiceProvider { get; set; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<ShopDbContext>(builder =>
builder.UseSqlServer("DefaultConnection"));
services.AddIdentity<User, IdentityRole>()
.AddEntityFrameworkStores<ShopDbContext>()
.AddDefaultTokenProviders();
services.AddSqlServerDbContextFactory<ShopDbContext>();
services.AddScoped<IShopEFRepository, EFRepository<ShopDbContext>>();
Shop.Core.Configure.Configure.ConfigureServices(services);
services.AddScoped<IUpdateService, UpdateService>();
//services.AddSingleton<IBotService, BotService>();
services.AddHttpContextAccessor();
ServiceProvider = services.BuildServiceProvider();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddCors();
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
.GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero //the default for this setting is 5 minutes
};
options.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
{
context.Response.Headers.Add("Token-Expired", "true");
}
return Task.CompletedTask;
}
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("RequireAdminRole", policy => policy.RequireRole("Admin"));
options.AddPolicy("User", policy => policy.RequireRole("User"));
options.AddPolicy("ShopManager", policy => policy.RequireRole("Manager"));
options.AddPolicy("DeviceRole", policy => policy.RequireRole("Device"));
options.AddPolicy("OwnerRole", policy => policy.RequireRole("Owner"));
});
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(opt =>
{
opt.SerializerSettings.ReferenceLoopHandling =
Newtonsoft.Json.ReferenceLoopHandling.Ignore;
});
//services.AddCors();
Mapper.Reset();
services.AddAutoMapper(typeof(Startup));
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// loggerFactory.AddMongoFramework<InfoLog>(ServiceProvider);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(builder =>
{
builder.Run(async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message);
}
});
});
}
app.UseCors(x => x.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
app.UseAuthentication();
app.UseMvc();
}
}
此外,我将EFCore.DbContextFactory用于通用存储库。当我尝试构建数据库时,出现异常:
InvalidOperationException: Unable to resolve service for type
Shop.SQLData.ShopDbContext while attempting to activate
Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore Shop.SqlModel.User,Microsoft.AspNetCore.Identity.IdentityRole,Shop.SQLData.ShopDbContext,System.String,Microsoft.AspNetCore.Identity.IdentityUserClaim`1[System.String],Microsoft.AspNetCore.Identity.IdentityUserRole`1[System.String],Microsoft.AspNetCore.Identity.IdentityUserLogin`1[System.String],Microsoft.AspNetCore.Identity.IdentityUserToken`1[System.String],Microsoft.AspNetCore.Identity.IdentityRoleClaim`1[System.String]].
我认为问题出在我设置DbContextFactory的方式上,但是当我按照提供的示例进行操作时,我采用了相同的方法。
此外,我的连接字符串是:
"ConnectionStrings": {
"DefaultConnection": "User ID=sa; Password=123456;Server=.\\sqlexpress;Database=ShopDb;"
}
当我尝试使用Package Manager更新数据库生成数据库时,出现此错误:
Format of the initialization string does not conform to specification starting at index 0.
答案 0 :(得分:2)
public ShopDbContext(DbContextOptions options): base(options)
尝试将其更改为此
public ShopDbContext(DbContextOptions<ShopDbContext> options): base(options)
并更改
services.AddDbContextFactory<ShopDbContext>(builder =>
builder.UseSqlServer("DefaultConnection"));
对此
string connectionString = Configuration.GetConnectionString("DefaultConnection");
services.AddDbContextFactory<DbContext,ShopDbContext>(builder =>
builder.UseSqlServer(connectionString));