我想解释一下为什么你不应该为此使用种子方法。如果在添加任何列后更改数据库排序规则,则存在collation conflicts
如下风险
无法解决等于操作中“SQL_Latin1_General_CP1_CI_AS”和“Latin1_General_100_CI_AS”之间的排序规则冲突。
这是因为如果您更改数据库,ALTER DATABASE [YourDb] COLLATE [YourCollation]
您只会更改数据库排序规则,而不是以前创建的列。
T-SQL 中的示例:
DECLARE @DBName nvarchar(50), @SQLString nvarchar(200)
SET @DBName = db_name();
SET @SQLString = 'ALTER DATABASE [' + @DBName + '] COLLATE Latin1_General_100_CI_AS'
EXEC(@SQLString)
/* Find Collation of SQL Server Database */
SELECT DATABASEPROPERTYEX(@DBName, 'Collation')
/* Find Collation of SQL Server Database Table Column */
SELECT name, collation_name
FROM sys.columns
WHERE OBJECT_ID IN (SELECT OBJECT_ID
FROM sys.objects
WHERE type = 'U'
AND name = 'AspNetUsers')
AND name = 'FirstName'
因此,您需要在添加任何列之前更改数据库排序规则或单独更改每一列。可能的解决方案:
- @MathieuRenda https://stackoverflow.com/a/42576705/3850405
我会按照文档中的建议将其放入DbInterception.Add
派生自DbConfiguration
或 inApplication_Start
的类中。Global.asax
笔记:Wherever you put this code, be careful not to execute DbInterception.Add for the same interceptor more than once, or you'll get additional interceptor instances.
public class ApplicationDbConfiguration: DbConfiguration
{
public ApplicationDbConfiguration()
{
DbInterception.Add(new CreateDatabaseCollationInterceptor("Latin1_General_100_CI_AS"));
}
}
我也不会从接口继承,而是使用DbCommandInterceptor
Microsoft 在他们的示例中所做的实现。
using System.Data.Common;
using System.Data.Entity.Infrastructure.Interception;
using System.Text.RegularExpressions;
namespace Application.Repositories.EntityFramework
{
public class CreateDatabaseCollationInterceptor : DbCommandInterceptor
{
private readonly string _collation;
public CreateDatabaseCollationInterceptor(string collation)
{
_collation = collation;
}
public override void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
// Works for SQL Server
if (Regex.IsMatch(command.CommandText, @"^create database \[.*]$"))
{
command.CommandText += " COLLATE " + _collation;
}
}
}
}
更多信息在这里:https ://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/connection-resiliency-and-command-interception-与-the-entity-framework-in-an-asp-net-mvc-application
@steliosalex:https ://stackoverflow.com/a/22895703/3850405 。请注意,更改每一列也可能不够。您还需要处理存储过程的元数据和参数,并且类似地获取数据库在创建这些时所具有的排序规则。完全更改排序规则需要具有正确排序规则的 create database 命令。
@RahmiAksu https://stackoverflow.com/a/31119371/3850405注意:我认为这不是一个好的解决方案,但如果您使用它,请编辑第一个迁移。如果数据库已经在生产中,则不能使用。如果您有种子方法,Resetting the connection results in a different state than the initial login
则会引发异常。
您的 Seed SqlException 可以通过使用普通的 ADO.Net 连接来解决,因此不会重置上下文的连接。但是,如上所述,这可能会在以后导致很多错误。
using (var conn = new SqlConnection(context.Database.Connection.ConnectionString))
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText =
string.Format("ALTER DATABASE [{0}] COLLATE Latin1_General_100_CI_AS",
context.Database.Connection.Database));
conn.Open();
cmd.ExecuteNonQuery();
}
}
SqlException:重置连接会导致与初始登录不同的状态。登录失败。用户 '' 登录失败。无法继续执行,因为会话处于终止状态。
资源:
https://stackoverflow.com/a/50400609/3850405