是否有一個MigrationSqlGenerator供SQLite與實體框架一起使用?我只從devart中找到一個商業的。SQLite的實體框架MigrationSqlGenerator
找不到提供商'System.Data.SQLite'的MigrationSqlGenerator。在目標遷移配置 類中使用SetSqlGenerator方法使用 來註冊其他SQL生成器。
這是我做的:http://msdn.microsoft.com/en-gb/data/jj591621
是否有一個MigrationSqlGenerator供SQLite與實體框架一起使用?我只從devart中找到一個商業的。SQLite的實體框架MigrationSqlGenerator
找不到提供商'System.Data.SQLite'的MigrationSqlGenerator。在目標遷移配置 類中使用SetSqlGenerator方法使用 來註冊其他SQL生成器。
這是我做的:http://msdn.microsoft.com/en-gb/data/jj591621
我不認爲這有什麼,免費的,據我所知。
如果你不關心Devart商業dotConnect for SQLite
- 你可以嘗試自己實現一個 - 它可能不那麼簡單,但你可以使用EF源代碼(對於EF6,但這些部分非常相似, d說)。
http://entityframework.codeplex.com/
如果你看一看的SqlCeMigrationSqlGenerator源代碼(其他來源,我無法找到一個在官方網站上,但你可以下載並檢查)
...你會看到發電機相對簡單。當然這對於使用標準Sql客戶端作爲底層生成器的Ce來說。
SQLite將需要更多的工作,但可能不那麼辛苦。
而且,類似的事情,從衆所周知的源來在這裏EF - Can we use EF migrations with MySql
不要「我大喊」 :)我知道這是不是你在找什麼 - 但我認爲這是唯一的選擇。
我試圖開始一個自定義MigrationSqlGenerator但這並不像你說的那麼微不足道:-) 我不知道我是否真的構建了這個MigrationSqlGenerator,或者如果我在啓動時手動運行自寫的sql-querys,它可以更快地實現... 如果任何人有一個SQLite MigrationSqlGenerator我會拿... devarts免費dotConnect不支持遷移 – 2013-04-11 09:06:44
我知道這不是微不足道的:)但這是我擁有的最好的 - 那裏似乎沒有其他的解決方案。 – NSGaga 2013-04-11 10:30:53
雖然職務是開了很長一段時間,我會後我得到了什麼是基於我們的朋友NSGaga露面做。
我設法根據爲SQLCE開發的內容創建一個類「MigrationSqLiteGenerator」。該課程的代碼太大,可以在我的博客上下載。
在谷歌驅動器: https://drive.google.com/file/d/0B-NCqWnMQpBrQjkxMkxnVlRzb00/view?usp=sharing
這個類只有基礎知識,再加上是需要改進的一個起點。
22.Mar.2017編輯由@shiva:下面的代碼內嵌因此,如果谷歌雲端硬盤鏈接斷裂再次,你仍然可以訪問代碼。剛剛發現SO在答覆帖子中有30,000
字符限制,所以我不得不刪除代碼中的註釋。這是在32,000
性格與意見:)
// *-----------------------------------------------------------------*
// * *
// * CRIADO POR...: Julio C. Borges. *
// * DATA.........: 19/07/2013. *
// * MOTIVO.......: *
// * *
// *-----------------------------------------------------------------*
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity.Migrations.Model;
using System.Data.Entity.Migrations.Sql;
using System.Data.Metadata.Edm;
using System.Data.SQLite;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace ICM_Conexao.SqLite.Classes
{
/// <sumary>
/// MigrationSqLiteGenerator
/// </sumary>
public class MigrationSqLiteGenerator : MigrationSqlGenerator
{
#region Constantes
private const string pstrDefaultDateTime = "yyyy-MM-dd hh:mm:ss";
private const int pintDefaultStringMaxLength = 255;
private const int pintDefaultPrecisaoNumerica = 10;
private const byte pbytDefaultPrecisaoTempo = 7;
private const byte pintDefaultEscala = 0;
//private const string pstrNomeTabelaMigration = "__MigrationHistory";
#endregion
#region Instancias
private DbProviderManifest pprovProviderManifest;
private List<MigrationStatement> plstComandos;
private bool pblnGerouPrimaryKey;
#endregion
#region Método de Geração sobrescrito de MigratioSqlGenerator
public override IEnumerable<MigrationStatement> Generate(
IEnumerable<MigrationOperation> lstOperacoesMigrations, string strManifestoProvider)
{
plstComandos = new List<MigrationStatement>();
InicializaServicosProvider(strManifestoProvider);
GeraComandos(lstOperacoesMigrations);
return plstComandos;
}
#endregion
#region Métodos de geração dos comandos
protected virtual void Generate(CreateTableOperation opeCriacaoTabela)
{
// Preferencialmente não iremos gerar a tabela de dados do Migration
if (opeCriacaoTabela.Name.Contains("MigrationHistory"))
return;
using (var ltextWriter = TextWriter())
{
GeraComandoCriacaoTabela(opeCriacaoTabela, ltextWriter);
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(AddForeignKeyOperation opeChaveEstrangeira)
{
// Inicialmente não havera a criação de chave estrangeira
}
protected virtual void Generate(DropForeignKeyOperation dropForeignKeyOperation)
{
// Inicalmente não haverá a criação de chave estrangeira
}
protected virtual void Generate(CreateIndexOperation opeCriacaoIndex)
{
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("CREATE ");
if (opeCriacaoIndex.IsUnique)
ltextWriter.Write(" UNIQUE ");
ltextWriter.Write("INDEX ");
ltextWriter.Write(opeCriacaoIndex.Name);
ltextWriter.Write(" ON ");
ltextWriter.Write(RemoveDBO(opeCriacaoIndex.Table));
ltextWriter.Write("(");
for (int lintCount = 0; lintCount < opeCriacaoIndex.Columns.Count; lintCount++)
{
var lstrDadosColuna = opeCriacaoIndex.Columns[lintCount];
ltextWriter.Write(lstrDadosColuna);
if (lintCount < opeCriacaoIndex.Columns.Count - 1)
ltextWriter.WriteLine(",");
}
ltextWriter.Write(")");
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(DropIndexOperation opeDropIndex)
{
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("DROP INDEX ");
ltextWriter.Write(opeDropIndex.Name);
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(AddPrimaryKeyOperation opeAdicionaPrimaryKey)
{
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("ALTER TABLE ");
ltextWriter.Write(RemoveDBO(opeAdicionaPrimaryKey.Table));
ltextWriter.Write(" ADD CONSTRAINT ");
ltextWriter.Write(opeAdicionaPrimaryKey.Name);
ltextWriter.Write(" PRIMARY KEY ");
ltextWriter.Write("(");
for (int li = 0; li < opeAdicionaPrimaryKey.Columns.Count; li++)
{
var lstrDadosColuna = opeAdicionaPrimaryKey.Columns[li];
ltextWriter.Write(lstrDadosColuna);
if (li < opeAdicionaPrimaryKey.Columns.Count - 1)
ltextWriter.WriteLine(",");
}
ltextWriter.Write(")");
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(DropPrimaryKeyOperation opeDropPrimaryKey)
{
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("ALTER TABLE ");
ltextWriter.Write(RemoveDBO(opeDropPrimaryKey.Table));
ltextWriter.Write(" DROP CONSTRAINT ");
ltextWriter.Write(opeDropPrimaryKey.Name);
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(AddColumnOperation opeAdicionaColuna)
{
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("ALTER TABLE ");
ltextWriter.Write(RemoveDBO(opeAdicionaColuna.Table));
ltextWriter.Write(" ADD ");
var lcmColuna = opeAdicionaColuna.Column;
Generate(lcmColuna, ltextWriter, null);
if ((lcmColuna.IsNullable != null)
&& !lcmColuna.IsNullable.Value
&& (lcmColuna.DefaultValue == null)
&& (string.IsNullOrWhiteSpace(lcmColuna.DefaultValueSql))
&& !lcmColuna.IsIdentity
&& !lcmColuna.IsTimestamp
&& !lcmColuna.StoreType.Equals("rowversion", StringComparison.InvariantCultureIgnoreCase)
&& !lcmColuna.StoreType.Equals("timestamp", StringComparison.InvariantCultureIgnoreCase))
{
ltextWriter.Write(" DEFAULT ");
if (lcmColuna.Type == PrimitiveTypeKind.DateTime)
{
ltextWriter.Write(Generate(DateTime.Parse("1900-01-01 00:00:00", CultureInfo.InvariantCulture)));
}
else
{
ltextWriter.Write(Generate((dynamic)lcmColuna.ClrDefaultValue));
}
}
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(DropColumnOperation opeRemoveColuna)
{
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("ALTER TABLE ");
ltextWriter.Write(RemoveDBO(opeRemoveColuna.Table));
ltextWriter.Write(" DROP COLUMN ");
ltextWriter.Write(opeRemoveColuna.Name);
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(AlterColumnOperation opeAlteraColuna)
{
var lcmColuna = opeAlteraColuna.Column;
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("ALTER TABLE ");
ltextWriter.Write(RemoveDBO(opeAlteraColuna.Table));
ltextWriter.Write(" ALTER COLUMN ");
ltextWriter.Write(lcmColuna.Name);
ltextWriter.Write(" ");
ltextWriter.Write(ConstruirTipoColuna(lcmColuna));
if ((lcmColuna.IsNullable != null)
&& !lcmColuna.IsNullable.Value)
{
ltextWriter.Write(" NOT NULL");
}
ComandoSQL(ltextWriter);
}
if ((lcmColuna.DefaultValue == null) && string.IsNullOrWhiteSpace(lcmColuna.DefaultValueSql))
return;
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("ALTER TABLE ");
ltextWriter.Write(RemoveDBO(opeAlteraColuna.Table));
ltextWriter.Write(" ALTER COLUMN ");
ltextWriter.Write(lcmColuna.Name);
ltextWriter.Write(" DROP DEFAULT");
ComandoSQL(ltextWriter);
}
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("ALTER TABLE ");
ltextWriter.Write(RemoveDBO(opeAlteraColuna.Table));
ltextWriter.Write(" ALTER COLUMN ");
ltextWriter.Write(lcmColuna.Name);
ltextWriter.Write(" SET DEFAULT ");
ltextWriter.Write(
(lcmColuna.DefaultValue != null)
? Generate((dynamic)lcmColuna.DefaultValue)
: lcmColuna.DefaultValueSql
);
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(DropTableOperation opeDropTable)
{
using (var ltextWriter = TextWriter())
{
ltextWriter.Write("DROP TABLE ");
ltextWriter.Write(RemoveDBO(opeDropTable.Name));
ComandoSQL(ltextWriter);
}
}
protected virtual void Generate(SqlOperation opeSQL)
{
ComandoSQL(opeSQL.Sql, opeSQL.SuppressTransaction);
}
protected virtual void Generate(RenameColumnOperation opeRenomearColuna)
{
// Inicialmente não suportada
}
protected virtual void Generate(RenameTableOperation opeRenameTable)
{
}
protected virtual void Generate(MoveTableOperation opeMoveTable)
{
}
private void Generate(ColumnModel cmDadosColuna, IndentedTextWriter textWriter, PrimaryKeyOperation opePrimaryKey)
{
textWriter.Write(cmDadosColuna.Name);
textWriter.Write(" ");
bool lblnEhPrimaryKey = false;
if (opePrimaryKey != null)
lblnEhPrimaryKey = opePrimaryKey.Columns.Contains(cmDadosColuna.Name);
if (lblnEhPrimaryKey)
{
if ((cmDadosColuna.Type == PrimitiveTypeKind.Int16) ||
(cmDadosColuna.Type == PrimitiveTypeKind.Int32))
textWriter.Write(" INTEGER ");
else
textWriter.Write(ConstruirTipoColuna(cmDadosColuna));
if (cmDadosColuna.IsIdentity)
{
textWriter.Write(" PRIMARY KEY AUTOINCREMENT ");
pblnGerouPrimaryKey = true;
}
}
else
{
textWriter.Write(ConstruirTipoColuna(cmDadosColuna));
if ((cmDadosColuna.IsNullable != null)
&& !cmDadosColuna.IsNullable.Value)
{
textWriter.Write(" NOT NULL");
}
if (cmDadosColuna.DefaultValue != null)
{
textWriter.Write(" DEFAULT ");
textWriter.Write(Generate((dynamic)cmDadosColuna.DefaultValue));
}
else if (!string.IsNullOrWhiteSpace(cmDadosColuna.DefaultValueSql))
{
textWriter.Write(" DEFAULT ");
textWriter.Write(cmDadosColuna.DefaultValueSql);
}
}
}
protected virtual void Generate(HistoryOperation opeHistorico)
{
// Foi removido, pois atualmente não usaremos o Migration
//using (var ltextWriter = TextWriter())
//{
// if (opeHistorico is InsertHistoryOperation)
// {
// InsertHistoryOperation lhisOperacaoInsert = opeHistorico as InsertHistoryOperation;
// ltextWriter.Write(" INSERT INTO ");
// ltextWriter.Write(pstrNomeTabelaMigration);
// ltextWriter.Write(" (MigrationId, Model, ProductVersion) VALUES ");
// ltextWriter.Write(string.Format(" ('{0}', {1}, '{2}')",
// lhisOperacaoInsert.MigrationId,
// Generate(lhisOperacaoInsert.Model), lhisOperacaoInsert.ProductVersion));
// }
// else if (opeHistorico is DeleteHistoryOperation)
// {
// DeleteHistoryOperation lhisOperacaoInsert = opeHistorico as DeleteHistoryOperation;
// ltextWriter.Write(" DELETE FROM ");
// ltextWriter.Write(pstrNomeTabelaMigration);
// ltextWriter.Write(string.Format(" WHERE MigrationId = '{0}'",
// lhisOperacaoInsert.MigrationId));
// }
// ComandoSQL(ltextWriter);
//}
}
protected virtual string Generate(byte[] bytDefaultValue)
{
var lstrbHexString = new StringBuilder();
foreach (var lbtByte in bytDefaultValue)
lstrbHexString.Append(lbtByte.ToString("X2", CultureInfo.InvariantCulture));
return "x'" + lstrbHexString + "'";
}
protected virtual string Generate(bool blnDefaultValue)
{
return blnDefaultValue ? "1" : "0";
}
protected virtual string Generate(DateTime dtmDefaultValue)
{
return "'" + dtmDefaultValue.ToString(pstrDefaultDateTime, CultureInfo.InvariantCulture) + "'";
}
protected virtual string Generate(DateTimeOffset dtfDefaultValue)
{
return "'" + dtfDefaultValue.ToString(pstrDefaultDateTime, CultureInfo.InvariantCulture) + "'";
}
protected virtual string Generate(Guid guidDefaultValue)
{
return "'" + guidDefaultValue + "'";
}
protected virtual string Generate(string strDefaultValue)
{
return "'" + strDefaultValue + "'";
}
protected virtual string Generate(TimeSpan tsDefaultValue)
{
return "'" + tsDefaultValue + "'";
}
protected virtual string Generate(object objDefaultValue)
{
return string.Format(CultureInfo.InvariantCulture, "{0}", objDefaultValue);
}
#endregion
#region Métodos auxiliares
protected virtual string ConstruirTipoColuna(ColumnModel cmModeloColuna)
{
return cmModeloColuna.IsTimestamp ? "rowversion" : ConstruirTipoPropriedade(cmModeloColuna);
}
private string ConstruirTipoPropriedade(ColumnModel propModeloPropriedade)
{
var lstrOriginalStoreTypeName = propModeloPropriedade.StoreType;
if (string.IsNullOrWhiteSpace(lstrOriginalStoreTypeName))
{
var ltypeUsage = pprovProviderManifest.GetStoreType(propModeloPropriedade.TypeUsage).EdmType;
lstrOriginalStoreTypeName = ltypeUsage.Name;
}
var lstrStoreTypeName = lstrOriginalStoreTypeName;
const string lstrSufixoMax = "(max)";
if (lstrStoreTypeName.EndsWith(lstrSufixoMax, StringComparison.Ordinal))
lstrStoreTypeName = lstrStoreTypeName.Substring(0, lstrStoreTypeName.Length - lstrSufixoMax.Length) + lstrSufixoMax;
switch (lstrOriginalStoreTypeName.ToLowerInvariant())
{
case "decimal":
case "numeric":
lstrStoreTypeName += "(" + (propModeloPropriedade.Precision ?? pintDefaultPrecisaoNumerica)
+ ", " + (propModeloPropriedade.Scale ?? pintDefaultEscala) + ")";
break;
case "datetime":
case "time":
lstrStoreTypeName += "(" + (propModeloPropriedade.Precision ?? pbytDefaultPrecisaoTempo) + ")";
break;
case "blob":
case "varchar2":
case "varchar":
case "char":
case "nvarchar":
case "nvarchar2":
lstrStoreTypeName += "(" + (propModeloPropriedade.MaxLength ?? pintDefaultStringMaxLength) + ")";
break;
}
return lstrStoreTypeName;
}
protected void ComandoSQL(string strInstrucaoSQL, bool blnSuprimeTransacao = false)
{
plstComandos.Add(new MigrationStatement
{
Sql = strInstrucaoSQL,
SuppressTransaction = blnSuprimeTransacao
});
}
protected void ComandoSQL(IndentedTextWriter writer)
{
ComandoSQL(writer.InnerWriter.ToString());
}
protected static IndentedTextWriter TextWriter()
{
return new IndentedTextWriter(new StringWriter(CultureInfo.InvariantCulture));
}
private static string RemoveDBO(string strTexto)
{
return strTexto.Replace("dbo.", string.Empty);
}
private void GeraComandos(IEnumerable<MigrationOperation> lstOperacoesMigrations)
{
foreach (dynamic ldynOperacao in lstOperacoesMigrations)
Generate(ldynOperacao);
}
private void InicializaServicosProvider(string strManifestoProvider)
{
using (var lconConexao = CreateConnection())
{
pprovProviderManifest = DbProviderServices
.GetProviderServices(lconConexao)
.GetProviderManifest(strManifestoProvider);
}
}
protected virtual DbConnection CreateConnection()
{
return new SQLiteConnection();
}
private void GeraComandoCriacaoTabela(CreateTableOperation opeCriacaoTabela, IndentedTextWriter textWriter)
{
textWriter.WriteLine("CREATE TABLE " + RemoveDBO(opeCriacaoTabela.Name) + " (");
textWriter.Indent++;
for (int i = 0; i < opeCriacaoTabela.Columns.Count; i++)
{
ColumnModel lcmDadosColuna = opeCriacaoTabela.Columns.ToList()[i];
Generate(lcmDadosColuna, textWriter, opeCriacaoTabela.PrimaryKey);
if (i < opeCriacaoTabela.Columns.Count - 1)
textWriter.WriteLine(",");
}
if ((opeCriacaoTabela.PrimaryKey != null) && !pblnGerouPrimaryKey)
{
textWriter.WriteLine(",");
textWriter.Write("CONSTRAINT ");
textWriter.Write(RemoveDBO(opeCriacaoTabela.PrimaryKey.Name));
textWriter.Write(" PRIMARY KEY ");
textWriter.Write("(");
for (int li = 0; li < opeCriacaoTabela.PrimaryKey.Columns.Count; li++)
{
var lstrNomeColuna = opeCriacaoTabela.PrimaryKey.Columns[li];
textWriter.Write(lstrNomeColuna);
if (li < opeCriacaoTabela.PrimaryKey.Columns.Count - 1)
textWriter.WriteLine(",");
}
textWriter.WriteLine(")");
}
else
{
textWriter.WriteLine();
}
textWriter.Indent--;
textWriter.Write(")");
}
#endregion
}
}
鏈接已損壞。你能否更新它或發佈代碼? – 2014-10-24 07:31:51
好@RobotMess我編輯了這篇文章,並將文件發送到Google Drive – 2014-12-29 16:51:27
@RobotMess我發佈了它內聯。看起來像SO有30K字符限制,代碼超過了32K個字符,所以我只刪除了代碼註釋,並將其降至30K以下。 – Shiva 2017-03-23 05:04:08
我認爲,我們可以使用Android相同的概念製作一個簡單的遷移引擎SQLite的。這post顯示了這個概念。當然,我們沒有任何工作的MigrationSqlGenerator,但這個概念是可靠的和有用的。
我不知道任何SQLite,但如果你想嘗試創建一個像其他人所建議的,你可以使用這個開源項目開始。或者你可能會發現這樣就足夠了嗎?
http://www.codeproject.com/Articles/32977/Upgrade-framework-for-SQLite-databases
對於任何人誰是尋找一個處理的遷移,以及我發現在https://sqliteef6migrations.codeplex.com一個NuGet包名爲「System.Data.SQLite.EF6.Migrations」發電機。
安裝軟件包後,需要對Migrations配置方法進行以下更改。
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("System.Data.SQLite", new SQLiteMigrationSqlGenerator());
}
完整的類應該看起來像這樣。
namespace YourNamespace
{
using System.Data.Entity.Migrations;
using System.Data.SQLite.EF6.Migrations;
internal sealed class Configuration : DbMigrationsConfiguration<YourContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetSqlGenerator("System.Data.SQLite", new SQLiteMigrationSqlGenerator());
}
protected override void Seed(YourContext context)
{
// This method will be called after migrating to the latest version.
}
}
}
據我所知唯一一個從C#SQLite的通信方法是使用[源碼網(https://github.com/praeclarum/sqlite-net) – outcoldman 2013-04-08 19:20:57
通信沒有問題。但是對於一個遷移工作框實體框架需要一個MigrationSqlGenerator,它不與sqlite庫一起交付 – 2013-04-08 19:33:09
這是一個正在工作的版本:https://github.com/msallin/SQLiteCodeFirst/issues/4 – 2016-03-03 03:48:51