- 1 - Conhecer o método ToQueryString
- 2 - Depuração com DebugView
- 3 - Redefinir o estado do seu contexto
- 4 - Include com consulta filtrada
- 5 - SingleOrDefault vs FirstOrDefault
- 6 - Tabela sem chave primária
- 7 - Usando Views de seu banco de dados
- 8 - Forçar o uso do VARCHAR
- 9 - Aplicar conversão de nomeclatura
- 10 - Operadores de agregação
- 11 - Operadores de agregação no agrupamento
- 12 - Contadores de eventos
using var db = new ApplicationContext();
var query = db.Departamentos.Where(x => x.Id == 2);
var sql = query.ToQueryString();
Console.WriteLine(sql);
Ideal para ambientes de teste
db.ChangeTracker.Clear();
using var db = new ApplicationContext();
var sql = db
.Departamentos
.Include(p => p.Colaboradores.Where(x => x.Nome.StartsWith("Werter")))
.ToQueryString();
Console.WriteLine(sql);
Output:
SELECT [d].[Id], [d].[Descricao], [t].[Id], [t].[DepartamentoId], [t].[Nome]
FROM [Departamentos] AS [d]
LEFT JOIN (
SELECT [c].[Id], [c].[DepartamentoId], [c].[Nome]
FROM [Colaboradores] AS [c]
WHERE [c].[Nome] IS NOT NULL AND ([c].[Nome] LIKE N'Werter%')
) AS [t] ON [d].[Id] = [t].[DepartamentoId]
ORDER BY [d].[Id], [t].[Id]
SingleOrDefault: Quando existe mais de um elemento no resultado da consulta, gera uma exceção FirstOrDefault: Retorna null caso não encontre um elemento
- Quando você precisar de 0 ou 1 elemento da consulta.
- Protege de informações duplicadas. EX: Não pode retornar um CPF duplicado
- Internamente o EFCore gera um SQL com TOP(2)
- Quando você precisar apenas de 1 elemento da consulta.
- Internamente o EFCore gera um SQL com TOP(1)
O EFCore não faz persistência de entidades sem chave primária
[Keyless]
public class UsuarioFuncao
{
public Guid UsuarioId { get; set; }
public Guid FuncaoId { get; set; }
}
// Ou
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UsuarioFuncao>()
.HasNoKey();
}
db.Database.ExecuteSqlRaw(
@"CREATE VIEW vw_departamento_relatorio AS
SELECT
d.Descricao, COUNT(c.Id) AS Colaboradores
FROM Departamentos AS d
LEFT JOIN Colaboradores AS c ON c.DepartamentoId = d.Id
GROUP BY d.Descricao");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<DepartamentoRelatorio>(e =>
{
e.HasNoKey();
e.ToView("vw_departamento_relatorio");
e.Property(x => x.Departamento)
.HasColumnName("Descricao");
});
}
var camposNVarchar = modelBuilder.Model.GetEntityTypes()
.SelectMany(x => x.GetProperties())
.Where(x => x.ClrType == typeof(string) && x.GetColumnType() == null);
foreach (var property in camposNVarchar)
property.SetIsUnicode(false);
public static class SnakeCaseExtensions
{
public static void ToSnakeCaseNames(this ModelBuilder modelBuilder)
{
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
var tableName = entity.GetTableName().ToSnakeCase();
entity.SetTableName(tableName);
foreach (var property in entity.GetProperties())
{
var storeObjectIdentifier = StoreObjectIdentifier.Table(tableName, null);
var columnName = property.GetColumnName(storeObjectIdentifier).ToSnakeCase();
property.SetColumnName(columnName);
}
foreach (var key in entity.GetKeys())
{
var keyName = key.GetName().ToSnakeCase();
key.SetName(keyName);
}
foreach (var key in entity.GetForeignKeys())
{
var foreignKeyName = key.GetConstraintName().ToSnakeCase();
key.SetConstraintName(foreignKeyName);
}
foreach (var index in entity.GetIndexes())
{
var indexName = index.GetDatabaseName().ToSnakeCase();
index.SetDatabaseName(indexName);
}
}
}
private static string ToSnakeCase(this string name) =>
Regex.Replace(name, @"([a-z0-9])([A-Z])", "$1_$2").ToLower();
}
modelBuilder.ToSnakeCaseNames();
using var db = new ApplicationContext();
var sql = db.Departamentos
.GroupBy(x => x.Descricao)
.Select(x => new
{
Descricao = x.Key,
Contador = x.Count(),
Media = x.Average(y => y.Id),
Maximo = x.Max(y => y.Id),
Soma = x.Sum(y => y.Id)
}).ToQueryString();
Console.WriteLine(sql);
SELECT [d].[descricao] AS [Descricao],
COUNT(*) AS [Contador],
AVG(CAST([d].[id] AS float)) AS [Media],
MAX([d].[id]) AS [Maximo],
COALESCE(SUM([d].[id]), 0) AS [Soma]
FROM [departamentos] AS [d]
GROUP BY [d].[descricao]
using var db = new ApplicationContext();
var sql = db.Departamentos
.GroupBy(x => x.Descricao)
.Where(x => x.Count() > 1)
.Select(x => new
{
Descricao = x.Key,
Contador = x.Count(),
Media = x.Average(y => y.Id),
Maximo = x.Max(y => y.Id),
Soma = x.Sum(y => y.Id)
}).ToQueryString();
Console.WriteLine(sql);
SELECT [d].[descricao] AS [Descricao],
COUNT(*) AS [Contador],
AVG(CAST([d].[id] AS float)) AS [Media],
MAX([d].[id]) AS [Maximo],
COALESCE(SUM([d].[id]), 0) AS [Soma]
FROM [departamentos] AS [d]
GROUP BY [d].[descricao]
HAVING COUNT(*) > 1
private static void ContadorDeEventos()
{
using var db = new ApplicationContext();
db.Database.EnsureDeleted();
db.Database.EnsureCreated();
Console.WriteLine($" PID: {System.Diagnostics.Process.GetCurrentProcess().Id}");
while (Console.ReadKey().Key != ConsoleKey.Escape)
{
var departamento = new Departamento
{
Descricao = "Departamento Contador de evento"
};
db.Departamentos.Add(departamento);
db.SaveChanges();
_ = db.Departamentos.Find(1);
_ = db.Departamentos.AsNoTracking().FirstOrDefault();
}
}
dotnet tool install --global dotnet-counters