Começando rápido
April 17, 2026 · View on GitHub
Instalação
Opção 1: referência de projeto (recomendado para desenvolvimento local)
<ItemGroup>
<ProjectReference Include="../src/DbSqlLikeMem/DbSqlLikeMem.csproj" />
<ProjectReference Include="../src/DbSqlLikeMem.SqlServer/DbSqlLikeMem.SqlServer.csproj" />
</ItemGroup>
Opção 2: referência a DLLs compiladas
dotnet build src/DbSqlLikeMem.slnx
Depois referencie no projeto de testes:
DbSqlLikeMem.dll- uma DLL de provider (ex.:
DbSqlLikeMem.SqlServer.dll)
Opção 3: pacote NuGet (recomendado para consumo em times)
Instale apenas o provider que representa o banco que você quer simular. O pacote core (DbSqlLikeMem) entra como dependência transitiva.
Exemplos:
dotnet add package DbSqlLikeMem.SqlServer
dotnet add package DbSqlLikeMem.SqlAzure
dotnet add package DbSqlLikeMem.Npgsql
dotnet add package DbSqlLikeMem.MySql
dotnet add package DbSqlLikeMem.Oracle
dotnet add package DbSqlLikeMem.Sqlite
dotnet add package DbSqlLikeMem.Db2
NuGet e dependências
Cada provider é empacotado separadamente (ex.: DbSqlLikeMem.MySql, DbSqlLikeMem.Npgsql).
Durante o dotnet pack, cada provider inclui dependência de DbSqlLikeMem.
Assim, ao instalar um provider via nuget.org, o núcleo é instalado automaticamente.
Dica: escolha um provider por projeto de teste (ou por suíte), conforme o dialeto que você precisa validar.
Compatibilidade de frameworks
Os pacotes de produção seguem os alvos centrais de src/code/Directory.Build.props: net462, netstandard2.0 e net8.0.
Os projetos de teste e test-tools usam o override dedicado: net462, net6.0 e net8.0.
Se houver impacto de distribuição ou versionamento, revise também docs/publishing.md.
Seleção de provider em runtime
Quando o banco é escolhido em tempo de execução, use uma factory:
using DbSqlLikeMem.MySql;
using DbSqlLikeMem.Npgsql;
using DbSqlLikeMem.Oracle;
using DbSqlLikeMem.SqlAzure;
using DbSqlLikeMem.Sqlite;
using DbSqlLikeMem.SqlServer;
using DbSqlLikeMem.Db2;
public static class DbSqlLikeMemFactory
{
public static DbConnection Create(string provider)
{
return provider.ToLowerInvariant() switch
{
"mysql" => new MySqlConnectionMock(new MySqlDbMock()),
"sqlserver" => new SqlServerConnectionMock(new SqlServerDbMock()),
"sqlazure" or "azure-sql" or "azuresql" or "azure_sql" => new SqlAzureConnectionMock(new SqlAzureDbMock()),
"oracle" => new OracleConnectionMock(new OracleDbMock()),
"postgres" or "postgresql" or "npgsql" => new NpgsqlConnectionMock(new NpgsqlDbMock()),
"sqlite" or "sqlite3" => new SqliteConnectionMock(new SqliteDbMock()),
"db2" => new Db2ConnectionMock(new Db2DbMock()),
_ => throw new ArgumentException($"Unsupported provider: {provider}")
};
}
}
Se carregar DLLs dinamicamente, garanta que o assembly do provider esteja disponível ao test runner.
Setup para testes (InternalsVisibleTo)
Se um assembly de testes customizado precisar acessar internal, adicione InternalsVisibleTo no core ou via AssemblyInfo.cs:
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("MyCustomTestAssembly")]
Exemplos de uso
Exemplo 1: schema fluente + execução compatível com Dapper (SQL Server)
using DbSqlLikeMem.SqlServer;
var db = new SqlServerDbMock { ThreadSafe = true };
using var connection = new SqlServerConnectionMock(db);
connection.DefineTable("user")
.Column<int>("id", pk: true, identity: true)
.Column<string>("name")
.Column<string>("email", nullable: true)
.Column<DateTime>("created", nullable: false);
connection.Open();
connection.Execute(
"INSERT INTO user (name, email, created) VALUES (@name, @email, @created)",
new { name = "Alice", email = "alice@mail.com", created = DateTime.UtcNow });
var users = connection.Query("SELECT * FROM user").ToList();
Exemplo 1b: criação de tabela via SQL + seed básico (SQL Server)
using DbSqlLikeMem.SqlServer;
var db = new SqlServerDbMock { ThreadSafe = true };
using var connection = new SqlServerConnectionMock(db);
connection.Open();
connection.Execute("CREATE TABLE users (Id INT PRIMARY KEY, Name VARCHAR(100) NOT NULL)");
connection.Execute("INSERT INTO users (Id, Name) VALUES (1, 'Alice')");
var users = connection.Query("SELECT * FROM users").ToList();
EN: This path is useful when you want to validate the DDL parser in addition to the fluent AddTable mapping.
PT-BR: Esse caminho é útil quando você quer validar o parser de DDL além do mapeamento fluente via AddTable.
Exemplo 2: schema manual + seed (PostgreSQL)
using DbSqlLikeMem.Npgsql;
var db = new NpgsqlDbMock();
var table = db.AddTable("Users");
table.Columns["Id"] = new(0, DbType.Int32, false);
table.Columns["Name"] = new(1, DbType.String, false);
table.Add(new Dictionary<int, object?>
{
{ 0, 1 },
{ 1, "John Doe" }
});
using var connection = new NpgsqlConnectionMock(db);
var result = connection.Query("SELECT * FROM Users WHERE Id = @Id", new { Id = 1 });
Exemplo 3: inspeção de plano de execução e métricas
using DbSqlLikeMem.MySql;
using var cnn = new MySqlConnectionMock();
cnn.Define("users");
cnn.Column<int>("users", "Id");
cnn.Column<int>("users", "Active");
cnn.Seed("users", null, [1, 1], [2, 0], [3, 1]);
using var cmd = new MySqlCommandMock(cnn)
{
CommandText = "SELECT Id FROM users WHERE Active = 1 ORDER BY Id"
};
using var reader = cmd.ExecuteReader();
while (reader.Read())
{
// consume rows
}
Console.WriteLine(cnn.LastExecutionPlan);
// Campos úteis no plano:
// - EstimatedCost
// - InputTables
// - EstimatedRowsRead
// - ActualRows
// - SelectivityPct
// - RowsPerMs
// - ElapsedMs
Observações:
LastExecutionPlantraz o último plano gerado para a conexão.LastExecutionPlansmantém o histórico da última execução do comando (útil para SQL com múltiplos SELECTs).- O plano também fica disponível no resultado (
TableResultMock.ExecutionPlan) internamente no executor AST.
Exemplo 4: sequence por schema + override opcional de identity
using DbSqlLikeMem.SqlServer;
var db = new SqlServerDbMock();
db.CreateSchema("sales");
var orders = db.AddTable("orders", schemaName: "sales");
orders.AddColumn("id", DbType.Int64, false, identity: true);
orders.AddColumn("description", DbType.String, false);
orders.IdentityOf(nextIdentity: 100, allowInsertOverride: true);
using var connection = new SqlServerConnectionMock(db, "sales");
connection.Open();
connection.AddSequence("seq_orders", startValue: 1000, incrementBy: 5, schemaName: "sales");
connection.Execute("INSERT INTO sales.orders (id, description) VALUES (150, 'manual identity')");
connection.Execute("INSERT INTO sales.orders (id, description) VALUES (NEXT VALUE FOR sales.seq_orders, 'sequence value')");
var ids = connection.Query<long>("SELECT id FROM sales.orders ORDER BY id").ToList();
Observações do exemplo:
IdentityOf(..., allowInsertOverride: true)libera sobrescrita explícita da colunaidentitysó para esse cenário.AddSequence(..., schemaName: "sales")registra a sequence no schema correto.- Para SQL Server e PostgreSQL, os fluxos validados hoje cobrem
SELECTeINSERTcom sequence simples e qualificada por schema; no PostgreSQL, o mock também cobrecurrval(...),setval(...)elastval().
Exemplo 5: funções de sequence no PostgreSQL
using DbSqlLikeMem.Npgsql;
var db = new NpgsqlDbMock();
using var connection = new NpgsqlConnectionMock(db);
connection.Open();
connection.AddSequence("seq_orders", startValue: 10, incrementBy: 2);
var first = connection.ExecuteScalar<long>("SELECT nextval('seq_orders')");
var current = connection.ExecuteScalar<long>("SELECT currval('seq_orders')");
var updated = connection.ExecuteScalar<long>("SELECT setval('seq_orders', 30, false)");
var next = connection.ExecuteScalar<long>("SELECT nextval('seq_orders')");
var last = connection.ExecuteScalar<long>("SELECT lastval()");
Observações do exemplo:
currval(...)elastval()são locais da sessão/conexão.setval(..., false)faz o próximonextval(...)retornar exatamente o valor informado.
Exemplo 6: sintaxe Oracle e DB2 para sequence
using DbSqlLikeMem.Oracle;
using DbSqlLikeMem.Db2;
var oracleDb = new OracleDbMock();
using var oracle = new OracleConnectionMock(oracleDb);
oracle.Open();
oracle.AddSequence("seq_orders", startValue: 100, incrementBy: 10);
var oracleNext = oracle.ExecuteScalar<long>("SELECT seq_orders.NEXTVAL");
var oracleCurr = oracle.ExecuteScalar<long>("SELECT seq_orders.CURRVAL");
var db2Db = new Db2DbMock();
using var db2 = new Db2ConnectionMock(db2Db);
db2.Open();
db2.AddSequence("seq_orders", startValue: 50, incrementBy: 5);
var db2Next = db2.ExecuteScalar<long>("VALUES NEXT VALUE FOR seq_orders");
var db2Previous = db2.ExecuteScalar<long>("VALUES PREVIOUS VALUE FOR seq_orders");
Observações do exemplo:
- Oracle usa
seq.NEXTVALeseq.CURRVAL. - DB2 usa
NEXT VALUE FOR seqePREVIOUS VALUE FOR seq. - Os dois caminhos também aceitam nomes qualificados por schema no mock.
Checklist rápido de revisão de documentação
Use esta lista quando fizer alterações grandes no código:
- Atualize a tabela de provedores/versões em
README.mdedocs/old/providers-and-features.md. - Verifique se exemplos de
factorycobrem todos os providers suportados. - Confirme se novos recursos aparecem em pelo menos um guia de uso (
docs/getting-started.md) e um guia de referência (docs/old/providers-and-features.md). - Se houver impacto de distribuição, revise
docs/publishing.md.
Testes
dotnet test src/DbSqlLikeMem.slnx