Skip to content

Instantly share code, notes, and snippets.

@hazzik
Created May 8, 2014 00:26
Show Gist options
  • Save hazzik/c08eabc7dffdca83eb55 to your computer and use it in GitHub Desktop.
Save hazzik/c08eabc7dffdca83eb55 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity.ModelConfiguration.Configuration;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using DelegateDecompiler;
namespace TestEncapsulation
{
public class ShoppingCartContext : DbContext
{
public ShoppingCartContext()
: base("name=Model1")
{
}
public virtual DbSet<Customer> Customers { get; set; }
public virtual DbSet<Order> Orders { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Customer>().HasMany(x => x.Orders);
base.OnModelCreating(modelBuilder);
}
}
public static class EntityTypeConfigurationEx
{
private static readonly EntityFrameworkMappingConfiguration cfg = new EntityFrameworkMappingConfiguration();
static EntityTypeConfigurationEx()
{
Configuration.Configure(cfg);
}
public static ManyNavigationPropertyConfiguration<TEntityType, TTargetEntity> HasMany<TEntityType, TTargetEntity>(
this EntityTypeConfiguration<TEntityType> c,
Expression<Func<TEntityType, IEnumerable<TTargetEntity>>> navigationPropertyExpression)
where TTargetEntity : class where TEntityType : class
{
var body = navigationPropertyExpression.Body;
var member = (PropertyInfo) ((MemberExpression) body).Member;
cfg.RegisterForDecompilation(member);
var decompile = DecompileExpressionVisitor.Decompile(body);
var convert = Expression.Convert(decompile, typeof (ICollection<TTargetEntity>));
var expression = Expression.Lambda<Func<TEntityType, ICollection<TTargetEntity>>>(convert, navigationPropertyExpression.Parameters);
return c.HasMany(expression);
}
}
public class EntityFrameworkMappingConfiguration : DefaultConfiguration
{
private readonly HashSet<MemberInfo> members = new HashSet<MemberInfo>();
public void RegisterForDecompilation(MemberInfo member)
{
members.Add(member);
}
public override bool ShouldDecompile(MemberInfo member)
{
return members.Contains(member) || base.ShouldDecompile(member);
}
}
public class Customer
{
protected virtual List<Order> _orders { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public virtual IEnumerable<Order> Orders
{
get { return _orders; }
}
}
public class Order
{
public int Id { get; set; }
public string Name { get; set; }
}
internal class Program
{
private static void Main(string[] args)
{
using (var db = new ShoppingCartContext())
{
var queryable = from c in db.Customers
from o in c.Orders
where o.Name == "x"
select c;
var customers = queryable.Decompile().ToList();
}
}
}
}
@jbogard
Copy link

jbogard commented May 8, 2014

That really compiles? When I use the EntityTypeConfiguration<T>, it forces me to use a property of ICollection<TEntity> for the HasMany method, so I can't even configure EF to map a collection property unless it's an ICollection.

@jbogard
Copy link

jbogard commented May 8, 2014

Ha, no wait, I see what you did there. Man, that is a dirty hack!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment