0

最近我减少了我的数据库权限,所以我不能删除和重新创建数据库。这导致我使用来自 nuget 的 DontDropDbJustCreateTablesIfModelChanged 数据库初始化。

但是,我现在不知道应该如何播种数据,因为 Seed 函数不在初始化中,所以我无法覆盖它。这是我希望能够做到的。

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"});
    }
}

在这种情况下是否有另一种播种数据的方法。

4

2 回答 2

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());
于 2013-09-18T23:26:56.890 回答
0

在我的项目中,我将数据库初始化与数据库播种分开。如果您使用控制反转,您应该能够在您的组合根目录中执行类似的操作(Application_Start,如果您正在使用来自 Web 应用程序的 DbContext):

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();
    }
}
于 2012-07-25T12:57:49.500 回答