Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist
View EfEncapsulateCollection.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
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 commented

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 commented

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
Something went wrong with that request. Please try again.