Skip to content

Instantly share code, notes, and snippets.

@trayburn
Created May 14, 2020 05:20
Show Gist options
  • Save trayburn/24c894118de80aa978e35c5f1b7c444c to your computer and use it in GitHub Desktop.
Save trayburn/24c894118de80aa978e35c5f1b7c444c to your computer and use it in GitHub Desktop.
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Query.SqlExpressions;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var bldr = new DbContextOptionsBuilder();
bldr.UseSqlServer("Server=.;Database=deleteme;Integrated Security=true;");
var context = new DemoDbContext(bldr.Options);
var query = context.Set<Url>()
.Join(context.Set<Click>(), e => e.Key, c => c.ShortUrlKey, (url, click) => new { Url = url, Click = click })
.GroupBy(e => new { e.Url.Key, e.Url.UrlString, e.Url.CreatedBy })
.Select(u => new
{
Key = u.Key.Key,
Url = u.Key.UrlString,
CreatedBy = u.Key.CreatedBy,
Clicks = u.Count()
});
Console.WriteLine(query.ToSql());
}
}
public class DemoDbContext : DbContext
{
public DemoDbContext([NotNullAttribute] DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Click>().HasKey(e => e.Id);
var urlBldr = modelBuilder.Entity<Url>();
urlBldr.Property(e => e.UrlString).HasColumnName("Url");
urlBldr.HasKey(e => e.Id);
base.OnModelCreating(modelBuilder);
}
}
public class Url
{
public Guid Id { get; set; }
public string UrlString { get; set; }
public string Key { get; set; }
public string CreatedBy { get; set; }
}
public class Click
{
public int Id { get; set; }
public string ShortUrlKey { get; set; }
public string CreatedBy { get; set; }
}
public static class EFHelper
{
public static string ToSql<TEntity>(this IQueryable<TEntity> query) where TEntity : class
{
var enumerator = query.Provider.Execute<IEnumerable<TEntity>>(query.Expression).GetEnumerator();
var relationalCommandCache = enumerator.Private("_relationalCommandCache");
var selectExpression = relationalCommandCache.Private<SelectExpression>("_selectExpression");
var factory = relationalCommandCache.Private<IQuerySqlGeneratorFactory>("_querySqlGeneratorFactory");
var sqlGenerator = factory.Create();
var command = sqlGenerator.GetCommand(selectExpression);
string sql = command.CommandText;
return sql;
}
private static object Private(this object obj, string privateField) => obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
private static T Private<T>(this object obj, string privateField) => (T)obj?.GetType().GetField(privateField, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(obj);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment