最近我的数据库权限已经减少,因此我无法删除并重新创建数据库。这导致我使用nuget的DontDropDbJustCreateTablesIfModelChanged数据库初始化。
然而,由于种子功能不在初始化中,因此我无法覆盖它,因此我现在不知道应该如何播种数据。这是我希望能够做到的。
public class MyDBInitialiser : DontDropDbJustCreateTablesIfModelChanged<MyContext>
{
protected override void Seed(MyContext context)
{
base.Seed(context);
context.Item.Add(new Item() { ItemId = 1, Name = "Item 1"});
context.Item.Add(new Item() { ItemId = 2, Name = "Item 2"});
context.Item.Add(new Item() { ItemId = 3, Name = "Item 3"});
}
}
在这种情况下是否存在另一种播种数据的方式。
答案 0 :(得分:1)
简单地说,
public class DontDropDbJustCreateTablesIfModelChanged<T>
: IDatabaseInitializer<T> where T : DbContext
{
private EdmMetadata _edmMetaData;
public void InitializeDatabase(T context)
{
ObjectContext objectContext =
((IObjectContextAdapter)context).ObjectContext;
string modelHash = GetModelHash(objectContext);
if (CompatibleWithModel(modelHash, context, objectContext))
return;
DeleteExistingTables(objectContext);
CreateTables(objectContext);
SaveModelHashToDatabase(context, modelHash, objectContext);
Seed(context);
}
protected virtual void Seed(T context) { }
private void SaveModelHashToDatabase(T context, string modelHash,
ObjectContext objectContext)
{
if (_edmMetaData != null) objectContext.Detach(_edmMetaData);
_edmMetaData = new EdmMetadata();
context.Set<EdmMetadata>().Add(_edmMetaData);
_edmMetaData.ModelHash = modelHash;
context.SaveChanges();
}
private void CreateTables(ObjectContext objectContext)
{
string dataBaseCreateScript =
objectContext.CreateDatabaseScript();
objectContext.ExecuteStoreCommand(dataBaseCreateScript);
}
private void DeleteExistingTables(ObjectContext objectContext)
{
objectContext.ExecuteStoreCommand(Dropallconstraintsscript);
objectContext.ExecuteStoreCommand(Deletealltablesscript);
}
private string GetModelHash(ObjectContext context)
{
var csdlXmlString = GetCsdlXmlString(context).ToString();
return ComputeSha256Hash(csdlXmlString);
}
private bool CompatibleWithModel(string modelHash, DbContext context,
ObjectContext objectContext)
{
var isEdmMetaDataInStore =
objectContext.ExecuteStoreQuery<int>(LookupEdmMetaDataTable)
.FirstOrDefault();
if (isEdmMetaDataInStore == 1)
{
_edmMetaData = context.Set<EdmMetadata>().FirstOrDefault();
if (_edmMetaData != null)
{
return modelHash == _edmMetaData.ModelHash;
}
}
return false;
}
private string GetCsdlXmlString(ObjectContext context)
{
if (context != null)
{
var entityContainerList = context.MetadataWorkspace
.GetItems<EntityContainer>(DataSpace.SSpace);
if (entityContainerList != null)
{
var entityContainer = entityContainerList.FirstOrDefault();
var generator =
new EntityModelSchemaGenerator(entityContainer);
var stringBuilder = new StringBuilder();
var xmlWRiter = XmlWriter.Create(stringBuilder);
generator.GenerateMetadata();
generator.WriteModelSchema(xmlWRiter);
xmlWRiter.Flush();
return stringBuilder.ToString();
}
}
return string.Empty;
}
private static string ComputeSha256Hash(string input)
{
byte[] buffer = new SHA256Managed()
.ComputeHash(Encoding.ASCII.GetBytes(input));
var builder = new StringBuilder(buffer.Length * 2);
foreach (byte num in buffer)
{
builder.Append(num.ToString("X2",
CultureInfo.InvariantCulture));
}
return builder.ToString();
}
private const string Dropallconstraintsscript =
@"select
'ALTER TABLE ' + so.table_name + ' DROP CONSTRAINT '
+ so.constraint_name
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS so";
private const string Deletealltablesscript =
@"declare @cmd varchar(4000)
declare cmds cursor for
Select
'drop table [' + Table_Name + ']'
From
INFORMATION_SCHEMA.TABLES
open cmds
while 1=1
begin
fetch cmds into @cmd
if @@fetch_status != 0 break
print @cmd
exec(@cmd)
end
close cmds
deallocate cmds";
private const string LookupEdmMetaDataTable =
@"Select COUNT(*)
FROM INFORMATION_SCHEMA.TABLES T
Where T.TABLE_NAME = 'EdmMetaData'";
}
&安培;
public class Population : DontDropDbJustCreateTablesIfModelChanged</* DbContext */>
{
protected override void Seed(Syndication Context)
{
/* Seeding :) */
}
}
&安培;
Database.SetInitializer</* DbContext */>(new Population());
答案 1 :(得分:0)
我的项目是我从数据库种子分割数据库初始化。如果您使用控制反转,您应该能够在合成根中执行类似的操作(如果您正在从Web应用程序中使用DbContext,则为Application_Start):
var seeder = ServiceLocatorPattern
.ServiceProviderLocator.Current.GetService<ISeedDb>();
if (seeder != null) seeder.Seed();
界面:
public interface ISeedDb, IDisposable
{
void Seed();
}
可能的实施:
public class MyDbSeeder : ISeedDb
{
private readonly MyContext _context;
public MyDbSeeder(MyContext context)
{
_context = context;
}
public void Seed()
{
_context.Item.Add(new Item { ItemId = 1, Name = "Item 1" });
// ... etc
}
public void Dispose()
{
_context.Dispose();
}
}