Skip to content

Instantly share code, notes, and snippets.

@DrSammyD
Last active February 12, 2019 21:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DrSammyD/11387939 to your computer and use it in GitHub Desktop.
Save DrSammyD/11387939 to your computer and use it in GitHub Desktop.
An expression generator to deep copy entities from one type to another, preserving reference loops.
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace EntityExpressionCopy
{
public static class CopyToExt
{
private static readonly ConcurrentDictionary<Type, LambdaExpression> CrateMergeStackFunc;
private static readonly ConcurrentDictionary<Type, Object> AssignDict;
public static MethodInfo AsQueryableMethod;
public static MethodInfo SelectMethod;
public static MethodInfo ToListMethod;
public static MethodInfo CopyToMethod;
public static MethodInfo CreateMergeMethod;
public static MethodInfo TryCopyMethod;
static CopyToExt()
{
AssignDict = new ConcurrentDictionary<Type, Object>(new Dictionary<Type, Object>());
CrateMergeStackFunc = new ConcurrentDictionary<Type, LambdaExpression>(new Dictionary<Type, LambdaExpression>());
foreach (MethodInfo m in typeof(Queryable).GetMethods().Where(m => m.Name == "Select"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("selector")))
if (p.ParameterType.GetGenericArguments().Any(x => x.GetGenericArguments().Count() == 2))
SelectMethod = (MethodInfo)p.Member;
foreach (MethodInfo m in typeof(Enumerable).GetMethods().Where(m => m.Name == "ToList"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("source")))
if (p.ParameterType.GetGenericArguments().Count() == 1)
ToListMethod = (MethodInfo)p.Member;
foreach (MethodInfo m in typeof(Queryable).GetMethods().Where(m => m.Name == "AsQueryable"))
foreach (ParameterInfo p in m.GetParameters().Where(p => p.Name.Equals("source")))
if (p.ParameterType.GetGenericArguments().Count() == 1)
AsQueryableMethod = (MethodInfo)p.Member;
TryCopyMethod = typeof(MergeStack).GetMethods().First(m => m.Name == "TryCopy");
}
public static IQueryable<TDest> CopyTo<TSrc, TDest>(this IQueryable<TSrc> queryable)
where TSrc : class, IEntity
where TDest : class, IEntity
{
return queryable.AsEnumerable().BaseCopyTo<TSrc, TDest>().AsQueryable();
}
public static IEnumerable<TDest> CopyTo<TSrc, TDest>(this IEnumerable<TSrc> queryable)
where TSrc : class, IEntity
where TDest : class, IEntity
{
return queryable.BaseCopyTo<TSrc, TDest>();
}
private static IEnumerable<TDest> BaseCopyTo<TSrc, TDest>(this IEnumerable<TSrc> enumerable)
{
var copyExpr = CreateTryCopy<TSrc, TDest>();
var merge = new MergeStack();
var ret= enumerable.Select(x=> new Stackholder<TSrc>{Ms = merge,Src = x}).AsQueryable().Select(copyExpr);
return ret;
}
public static Expression<Func<Stackholder<TSrc>, TDest>> CreateTryCopy<TSrc, TDest>()
{
return CrateMergeStackFunc.GetOrAdd(typeof(Func<Stackholder<TSrc>, TDest>), (type) =>
{
var shtype = typeof(Stackholder<TSrc>);
var parentParam = Expression.Parameter(shtype);
var srcExpr = Expression.PropertyOrField(parentParam, "Src");
var msExpr = Expression.PropertyOrField(parentParam, "Ms");
var tcMethod = Expression.Call(msExpr,
TryCopyMethod.MakeGenericMethod(new Type[] { typeof(TSrc), typeof(TDest) }),
srcExpr);
return Expression.Lambda<Func<Stackholder<TSrc>, TDest>>(tcMethod, parentParam);
}) as Expression<Func<Stackholder<TSrc>, TDest>>;
}
internal static bool Impliments(this Type type, Type inheritedType)
{
return (type.IsSubclassOf(inheritedType) || type.GetInterface(inheritedType.FullName) != null);
}
internal static bool Impliments<T>(this Type type, Type inheritedType = null)
{
return type.Impliments(typeof(T));
}
internal static Func<TSrc, TDest, MergeStack, TDest> Assign<TSrc, TDest>()
{
return (Func<TSrc, TDest, MergeStack, TDest>)AssignDict.GetOrAdd(typeof(Func<TSrc, TDest>), (indexType) =>
{
var tSrc = typeof(TSrc);
var tDest = typeof(TDest);
var srcEntityInterfaces = tSrc.GetInterfaces().Where(x => x.Impliments<IEntity>()).ToArray();
var destEntityInterfaces = tDest.GetInterfaces().Where(x => x.Impliments<IEntity>()).ToArray();
var srcParam = Expression.Parameter(tSrc);
var destParam = Expression.Parameter(tDest);
var msExpr = Expression.Parameter(typeof(MergeStack));
var common = destEntityInterfaces.Intersect(srcEntityInterfaces).ToArray();
var memberbindings = common.Where(x => x.Impliments<IEntityProperty>())
.Select(type => type.GetProperties().First())
.Select(
prop =>
Expression.Assign(Expression.Property(destParam, prop.Name),
Expression.Property(srcParam, prop.Name)))
.Cast<Expression>().ToList();
foreach (var type in common.Where(x => x.Impliments<IEntityObject>()))
{
var destSubType = destEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var srcSubType = srcEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var dProp = destEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var sProp = srcEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var tcParam = Expression.Parameter(srcSubType);
var tcMethod = Expression.Call(msExpr,
TryCopyMethod.MakeGenericMethod(new Type[] { srcSubType, destSubType }),
tcParam);
LambdaExpression mergeLambda = Expression.Lambda(tcMethod, tcParam);
MemberExpression memberExpression = Expression.Property(srcParam, sProp.Name);
InvocationExpression invocationExpression = Expression.Invoke(mergeLambda,
Expression.Property(srcParam, sProp.Name));
var check = Expression.Condition(
Expression.MakeBinary(ExpressionType.NotEqual, memberExpression,
Expression.Constant(null, sProp.PropertyType)), invocationExpression,
Expression.Constant(null, invocationExpression.Type));
BinaryExpression binaryExpression = Expression.Assign(Expression.Property(destParam, dProp.Name),
check);
memberbindings.Add(binaryExpression);
}
foreach (var type in common.Where(x => x.Impliments<IEntityCollection>()))
{
var destSubType = destEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var srcSubType = srcEntityInterfaces.First(x => x.Impliments(type))
.GetGenericArguments()
.First();
var dProp = destEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var sProp = srcEntityInterfaces.First(x => x.Impliments(type)).GetProperties().First();
var tcParam = Expression.Parameter(srcSubType);
var tcMethod = Expression.Call(msExpr,
TryCopyMethod.MakeGenericMethod(new Type[] { srcSubType, destSubType }),
tcParam);
LambdaExpression mergeLambda = Expression.Lambda(tcMethod, tcParam);
var memberExpression = Expression.Property(srcParam, sProp.Name);
var selectExpr = Expression.Call(null,
AsQueryableMethod.MakeGenericMethod(new Type[] { srcSubType }),
new Expression[] { memberExpression });
selectExpr = Expression.Call(null,
CopyToExt.SelectMethod.MakeGenericMethod(new Type[] { srcSubType, destSubType }),
new Expression[] { selectExpr, mergeLambda });
selectExpr = Expression.Call(null,
CopyToExt.ToListMethod.MakeGenericMethod(new Type[] { destSubType }),
new Expression[] { selectExpr });
var check = Expression.Condition(
Expression.MakeBinary(ExpressionType.NotEqual, memberExpression,
Expression.Constant(null, sProp.PropertyType)), selectExpr,
Expression.Constant(null, selectExpr.Type));
memberbindings.Add(Expression.Assign(Expression.Property(destParam, dProp.Name), check));
}
memberbindings.Add(destParam);
return
Expression.Lambda<Func<TSrc, TDest, MergeStack, TDest>>(Expression.Block(memberbindings),
new ParameterExpression[] { srcParam, destParam, msExpr }).Compile();
});
}
}
public class Stackholder<TSrc>
{
public MergeStack Ms;
public TSrc Src;
}
public class Enumerableholder<TSrc>
{
public IEnumerable Key;
public TSrc Src;
}
public class MergeStack
{
private readonly Dictionary<Type, Dictionary<Object, Object>> _mergeObjDict = new Dictionary<Type, Dictionary<object, object>>();
public TDest TryCopy<TSrc, TDest>(TSrc Src)
where TSrc : class, IEntity
where TDest : class, IEntity, new()
{
if (Src == null) return null;
var objToIndex = new TDest();
Dictionary<object, object> objToObj;
if (!_mergeObjDict.ContainsKey(objToIndex.GetType()))
{
objToObj = new Dictionary<object, object>();
_mergeObjDict.Add(objToIndex.GetType(), objToObj);
}
else
{
objToObj = _mergeObjDict[objToIndex.GetType()];
}
if (!objToObj.ContainsKey(Src))
{
objToObj.Add(Src, objToIndex);
return CopyToExt.Assign<TSrc, TDest>()(Src, objToIndex, this);
}
return objToObj[Src] as TDest;
}
}
public interface IEntity
{
}
public interface IEntityObject : IEntity
{
}
public interface IEntityCollection : IEntity
{
}
public interface IEntityProperty : IEntity
{
}
}
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><#@
output extension=".cs"#><#
const string inputFile = @"Model.edmx";
var textTransform = DynamicTextTransformation.Create(this);
var code = new CodeGenerationTools(this);
var ef = new MetadataTools(this);
var typeMapper = new TypeMapper(code, ef, textTransform.Errors);
var fileManager = EntityFrameworkTemplateFileManager.Create(this);
var itemCollection =
new EdmMetadataLoader(textTransform.Host, textTransform.Errors).CreateEdmItemCollection(inputFile);
var codeStringGenerator = new CodeStringGenerator(code, typeMapper, ef);
if (!typeMapper.VerifyCaseInsensitiveTypeUniqueness(typeMapper.GetAllGlobalItems(itemCollection), inputFile))
{
return string.Empty;
}
WriteHeader(codeStringGenerator, fileManager);
foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
{
fileManager.StartNewFile(entity.Name + ".cs");
BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false) #>
<#
var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
var complexProperties = typeMapper.GetComplexProperties(entity);
var simpleProperties = typeMapper.GetSimpleProperties(entity);
var navigationProperties = typeMapper.GetNavigationProperties(entity);
#>
<#=codeStringGenerator.EntityInterfaceOpening(entity) #>
{
}
<#
if (simpleProperties.Any())
{
foreach (var edmProperty in simpleProperties)
{
if (CodeStringGenerator.HasContract(edmProperty))
{
#>
<#=codeStringGenerator.EntityInterfaceOpening(entity, edmProperty)
#>, IEntityProperty
{
<#=codeStringGenerator.Contract(edmProperty) #>
}
<#
}
}
}
if (complexProperties.Any())
{
#>
<#
foreach (var complexProperty in complexProperties)
{
if (CodeStringGenerator.HasContract(complexProperty))
{
#>
<#=codeStringGenerator.EntityInterfaceOpening(entity, complexProperty)
#>
{
<#=codeStringGenerator.Contract(complexProperty) #>
}
<#
}
}
}
if (navigationProperties.Any())
{
#>
<#
foreach (var navigationProperty in navigationProperties)
{
if (CodeStringGenerator.HasContract(navigationProperty))
{
#>
<#=codeStringGenerator.EmptyInterfaceOpening(entity,navigationProperty)#>{}
<#=codeStringGenerator.EntityInterfaceOpening(entity, navigationProperty)
#> <#=codeStringGenerator.EntityInterfaceBaseOpening(entity,navigationProperty)#>
{
<#=codeStringGenerator.NavigationContract(navigationProperty) #>
}
<#
}
}
}
#>
<#=
codeStringGenerator.EntityInterfaceOpening(entity, simpleProperties, complexProperties, navigationProperties)
#>
{
}
<#=codeStringGenerator.EntityClassOpening(entity, simpleProperties, complexProperties, navigationProperties) #>
{
<#
if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
{
#>
public <#=code.Escape(entity) #>()
{
<#
foreach (var edmProperty in propertiesWithDefaultValues)
{
#>
this.<#=code.Escape(edmProperty) #> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue) #>;
<#
}
foreach (var navigationProperty in collectionNavigationProperties)
{
#>
this.<#=code.Escape(navigationProperty) #> = new HashSet<<#=typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType())
#>>();
<#
}
foreach (var complexProperty in complexProperties)
{
#>
this.<#=code.Escape(complexProperty) #> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage) #>();
<#
}
#>
}
<#
}
if (simpleProperties.Any())
{
foreach (var edmProperty in simpleProperties)
{
#>
<#=codeStringGenerator.Property(edmProperty) #>
<#
}
}
if (complexProperties.Any())
{
#>
<#
foreach (var complexProperty in complexProperties)
{
#>
<#=codeStringGenerator.Property(complexProperty) #>
<#
}
}
if (navigationProperties.Any())
{
#>
<#
foreach (var navigationProperty in navigationProperties)
{
#>
<#=codeStringGenerator.NavigationProperty(navigationProperty) #>
<#
}
}
#>
}
<#
EndNamespace(code);
}
foreach (var complex in typeMapper.GetItemsToGenerate<ComplexType>(itemCollection))
{
fileManager.StartNewFile(complex.Name + ".cs");
BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)
#>
<#=Accessibility.ForType(complex) #> partial class <#=code.Escape(complex) #>
{
<#
var complexProperties = typeMapper.GetComplexProperties(complex);
var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex);
if (propertiesWithDefaultValues.Any() || complexProperties.Any())
{
#>
public <#=code.Escape(complex) #>()
{
<#
foreach (var edmProperty in propertiesWithDefaultValues)
{
#>
this.<#=code.Escape(edmProperty) #> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue) #>;
<#
}
foreach (var complexProperty in complexProperties)
{
#>
this.<#=code.Escape(complexProperty) #> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage) #>();
<#
}
#>
}
<#
}
var simpleProperties = typeMapper.GetSimpleProperties(complex);
if (simpleProperties.Any())
{
foreach (var edmProperty in simpleProperties)
{
#>
<#=codeStringGenerator.Property(edmProperty) #>
<#
}
}
if (complexProperties.Any())
{
#>
<#
foreach (var edmProperty in complexProperties)
{
#>
<#=codeStringGenerator.Property(edmProperty) #>
<#
}
}
#>
}
<#
EndNamespace(code);
}
foreach (var enumType in typeMapper.GetEnumItemsToGenerate(itemCollection))
{
fileManager.StartNewFile(enumType.Name + ".cs");
BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false, includeCollections: false)
#>
<#
if (typeMapper.EnumIsFlags(enumType))
{
#>
[Flags]
<#
}
#>
<#=codeStringGenerator.EnumOpening(enumType) #>
{
<#
var foundOne = false;
foreach (MetadataItem member in typeMapper.GetEnumMembers(enumType))
{
foundOne = true;
#>
<#=code.Escape(typeMapper.GetEnumMemberName(member)) #> = <#=typeMapper.GetEnumMemberValue(member) #>,
<#
}
if (foundOne)
{
this.GenerationEnvironment.Remove(this.GenerationEnvironment.Length - 3, 1);
}
#>
}
<#
EndNamespace(code);
}
fileManager.Process();
#>
<#+
public void WriteHeader(CodeStringGenerator codeStringGenerator, EntityFrameworkTemplateFileManager fileManager)
{
fileManager.StartHeader();
#>
//------------------------------------------------------------------------------
// <auto-generated>
// <#=GetResourceString("Template_GeneratedCodeCommentLine1") #>
//
// <#=GetResourceString("Template_GeneratedCodeCommentLine2") #>
// <#=GetResourceString("Template_GeneratedCodeCommentLine3") #>
// </auto-generated>
//------------------------------------------------------------------------------
<#=codeStringGenerator.UsingDirectives(inHeader: true) #>
<#+
fileManager.EndBlock();
}
public void BeginNamespace(CodeGenerationTools code)
{
var codeNamespace = code.VsNamespaceSuggestion();
if (!String.IsNullOrEmpty(codeNamespace))
{
#>
namespace <#=code.EscapeNamespace(codeNamespace) #>
{
<#+
PushIndent(" ");
}
}
public void EndNamespace(CodeGenerationTools code)
{
if (!String.IsNullOrEmpty(code.VsNamespaceSuggestion()))
{
PopIndent();
#>
}
<#+
}
}
public const string TemplateId = "CSharp_DbContext_Types_EF5";
public class CodeStringGenerator
{
private readonly CodeGenerationTools _code;
private readonly TypeMapper _typeMapper;
private readonly MetadataTools _ef;
public CodeStringGenerator(CodeGenerationTools code, TypeMapper typeMapper, MetadataTools ef)
{
ArgumentNotNull(code, "code");
ArgumentNotNull(typeMapper, "typeMapper");
ArgumentNotNull(ef, "ef");
_code = code;
_typeMapper = typeMapper;
_ef = ef;
}
public string EntityVar(EntityType entity)
{
return (_code.Escape(entity)).ToLowerInvariant();
}
public string SrcProperty(EntityType entity, EdmMember edmMember)
{
return src(ContractInterfaceName(entity, edmMember));
}
public string DestProperty(EntityType entity, EdmMember edmMember)
{
return dest(ContractInterfaceName(entity, edmMember));
}
private string dest(string name)
{
return BaseDestName() + name;
}
private string src(string name)
{
return BaseSrcName() + name;
}
public string Property(EdmProperty edmProperty)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1} {2} {{ {3}get; {4}set; }}",
Accessibility.ForProperty(edmProperty),
_typeMapper.GetTypeName(edmProperty.TypeUsage),
_code.Escape(edmProperty),
_code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
_code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
}
public string Contract(EdmProperty edmProperty)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1} {{ get; set; }}",
_typeMapper.GetInterfaceName(edmProperty.TypeUsage),
_code.Escape(edmProperty));
}
public string GetContractOpening(EntityType entity, EdmMember edmProperty, bool fromEntity=false)
{
return string.Format(
CultureInfo.InvariantCulture,
"public static {1} {0}(this {2} {3})",
GetContractName(edmProperty),
_typeMapper.GetInterfaceName(edmProperty.TypeUsage.EdmType, true, null),
fromEntity ? _code.Escape(entity) : BaseInterfaceName(entity),
BaseSrcName());
}
public string SetContractOpening(EntityType entity,EdmMember edmMember, bool withMergeStack =false, bool toEntity=false)
{
string accessibility = withMergeStack ? "internal" : "public";
string mergeStackProp = withMergeStack ? ", MergeStack ms" : "";
return string.Format(
CultureInfo.InvariantCulture,
"{6} static void {0}(this {1} {2}, {3} {4}{5})",
SetContractName(edmMember),
toEntity ? _code.Escape(entity) : BaseInterfaceName(entity),
BaseDestName(),
_typeMapper.GetInterfaceName(edmMember.TypeUsage.EdmType, true, null),
BaseSrcName(),
mergeStackProp,
accessibility);
}
public string GetContractName(EdmMember edmMember)
{
return "Get_" + _code.Escape(edmMember);
}
public string SetContractName(EdmMember edmMember)
{
return "Set_" + _code.Escape(edmMember);
}
public String BaseSrcName()
{
return "src";
}
public String BaseDestName()
{
return "dest";
}
public string ContractNew(EdmProperty edmProperty)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}()",
_typeMapper.GetInterfaceName(edmProperty.TypeUsage),
"New" + _code.Escape(edmProperty));
}
public static bool HasContract(EdmMember edmMember)
{
return Accessibility.ForProperty(edmMember) == "public" ||
(Accessibility.ForGetter(edmMember) == "public" &&
Accessibility.ForSetter(edmMember) == "public");
}
public static bool RelationshipMany(NavigationProperty navigationProperty)
{
return navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many;
}
public string NavigationProperty(NavigationProperty navigationProperty)
{
var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1} {2} {{ {3}get; {4}set; }}",
AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many
? ("ICollection<" + endType + ">")
: endType,
_code.Escape(navigationProperty),
_code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
_code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
}
public string NavigationContract(NavigationProperty navigationProperty)
{
var endType = _typeMapper.GetInterfaceName(navigationProperty.ToEndMember.GetEntityType());
return string.Format(
CultureInfo.InvariantCulture,
"{1} {2} {{ {3}get; {4}set; }}",
Accessibility.ForProperty(navigationProperty),
navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many
? ("ICollection<" + endType + ">")
: endType,
_code.Escape(navigationProperty),
_code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
_code.SpaceAfter(Accessibility.ForSetter(navigationProperty)));
}
public string NavigationContractNew(NavigationProperty navigationProperty)
{
var endType = _typeMapper.GetInterfaceName(navigationProperty.ToEndMember.GetEntityType());
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}();",
endType,
NavigationContractNewName(navigationProperty));
}
public string NavigationContractNewName(NavigationProperty navigationProperty)
{
return "New" + _code.Escape((navigationProperty));
}
public string AccessibilityAndVirtual(string accessibility)
{
return accessibility + (accessibility != "private" ? " virtual" : "");
}
public string EntityClassOpening(EntityType entity,
IEnumerable<EdmProperty> edmProperties,
IEnumerable<EdmProperty> complexProperties,
IEnumerable<NavigationProperty> navigationProperties)
{
var edmInterfaces = edmProperties.Where(HasContract).Select(x => ContractInterfaceName(entity, x));
var complexInterfaces = complexProperties.Where(HasContract).Select(x => ContractInterfaceName(entity, x)+"<"+">");
var navigationInterfaces =
navigationProperties.Where(HasContract).Select(x => ContractInterfaceName(entity, x)+"<"+_typeMapper.GetTypeName(x.ToEndMember.GetEntityType())+">");
var interfaces = edmInterfaces.Concat(complexInterfaces).Concat(navigationInterfaces);
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}partial class {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
_code.Escape(entity),
_code.StringBefore(" : ", String.Join(", \n ", interfaces)));
}
public string EntityInterfaceOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}interface {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
BaseInterfaceName(entity),
_code.StringBefore(" : ", null));
}
public string EntityInterfaceOpening(EntityType entity, EdmProperty edmProperty)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}interface {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
ContractInterfaceName(entity, edmProperty),
_code.StringBefore(" : ", BaseInterfaceName(entity)));
}
public string EntityExtensionOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} static class {1}",
Accessibility.ForType(entity),
_typeMapper.GetInterfaceName(entity) + "Ext");
}
public string ContractInterfaceName(EntityType entity, EdmMember edmMember)
{
return BaseInterfaceName(entity) + "_" + _code.Escape(edmMember);
}
public string ContractInterfaceName(EntityType entity)
{
return BaseInterfaceName(entity) + "__All";
}
public string BaseInterfaceName(EntityType entity)
{
return "I" + _code.Escape(entity);
}
public string EntityInterfaceOpening(EntityType entity,
IEnumerable<EdmProperty> edmProperties,
IEnumerable<EdmProperty> complexProperties,
IEnumerable<NavigationProperty> navigationProperties)
{
var edmInterfaces = edmProperties.Where(HasContract).Select(x => ContractInterfaceName(entity, x));
var complexInterfaces = complexProperties.Where(HasContract).Select(x => ContractInterfaceName(entity, x));
var navigationInterfaces =
navigationProperties.Where(HasContract).Select(x => ContractInterfaceName(entity, x));
var interfaces = edmInterfaces;
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}interface {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
ContractInterfaceName(entity),
_code.StringBefore(" : ", String.Join(", \n ", interfaces)));
}
public string EntityInterfaceOpening(EntityType entity, NavigationProperty navigationProperty)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}interface {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
ContractInterfaceName(entity, navigationProperty)+"<T>",
_code.StringBefore(" : ", ContractInterfaceName(entity, navigationProperty).Split('<').First()));
}
public string EmptyInterfaceOpening(EntityType entity, NavigationProperty navigationProperty)
{
String type = _typeMapper.GetTypeName(navigationProperty.TypeUsage);
String bt = type.Contains("Collection")?"Collection":"Object";
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}interface {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
ContractInterfaceName(entity, navigationProperty),
_code.StringBefore(" : ", BaseInterfaceName(entity)+", IEntity"+bt));
}
public string EntityInterfaceBaseOpening(EntityType entity, NavigationProperty navigationProperty)
{
String type = _typeMapper.GetTypeName(navigationProperty.TypeUsage);
type = _typeMapper.GetTypeName(navigationProperty.TypeUsage).Split('<').Last();
type = type.Split('>').First();
return string.Format(
CultureInfo.InvariantCulture,
" where T : class, I{0}, new()",
type
);
}
public string EntityBaseInterfaceOpening(EntityType entity)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1}interface {2}{3}",
Accessibility.ForType(entity),
_code.SpaceAfter(_code.AbstractOption(entity)),
BaseInterfaceName(entity),
_code.StringBefore(" : ", null));
}
public string EnumOpening(SimpleType enumType)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} enum {1} : {2}",
Accessibility.ForType(enumType),
_code.Escape(enumType),
_code.Escape(_typeMapper.UnderlyingClrType(enumType)));
}
public void WriteFunctionParameters(EdmFunction edmFunction,
Action<string, string, string, string> writeParameter)
{
var parameters = FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
foreach (var parameter in parameters.Where(p => p.NeedsLocalVariable))
{
var isNotNull = parameter.IsNullableOfT
? parameter.FunctionParameterName + ".HasValue"
: parameter.FunctionParameterName + " != null";
var notNullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", " +
parameter.FunctionParameterName + ")";
var nullInit = "new ObjectParameter(\"" + parameter.EsqlParameterName + "\", typeof(" +
parameter.RawClrTypeName + "))";
writeParameter(parameter.LocalVariableName, isNotNull, notNullInit, nullInit);
}
}
public string ComposableFunctionMethod(EdmFunction edmFunction, string modelNamespace)
{
var parameters = _typeMapper.GetParameters(edmFunction);
return string.Format(
CultureInfo.InvariantCulture,
"{0} IQueryable<{1}> {2}({3})",
AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
_code.Escape(edmFunction),
string.Join(", ",
parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray()));
}
public string ComposableCreateQuery(EdmFunction edmFunction, string modelNamespace)
{
var parameters = _typeMapper.GetParameters(edmFunction);
return string.Format(
CultureInfo.InvariantCulture,
"return ((IObjectContextAdapter)this).ObjectCongtext.CreateQuery<{0}>(\"[{1}].[{2}]({3})\"{4});",
_typeMapper.GetTypeName(_typeMapper.GetReturnType(edmFunction), modelNamespace),
edmFunction.NamespaceName,
edmFunction.Name,
string.Join(", ", parameters.Select(p => "@" + p.EsqlParameterName).ToArray()),
_code.StringBefore(", ", string.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray())));
}
public string FunctionMethod(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
{
var parameters = _typeMapper.GetParameters(edmFunction);
var returnType = _typeMapper.GetReturnType(edmFunction);
var paramList = String.Join(", ",
parameters.Select(p => p.FunctionParameterType + " " + p.FunctionParameterName).ToArray());
if (includeMergeOption)
{
paramList = _code.StringAfter(paramList, ", ") + "MergeOption mergeOption";
}
return string.Format(
CultureInfo.InvariantCulture,
"{0} {1} {2}({3})",
AccessibilityAndVirtual(Accessibility.ForMethod(edmFunction)),
returnType == null ? "int" : "ObjectResult<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
_code.Escape(edmFunction),
paramList);
}
public string ExecuteFunction(EdmFunction edmFunction, string modelNamespace, bool includeMergeOption)
{
var parameters = _typeMapper.GetParameters(edmFunction);
var returnType = _typeMapper.GetReturnType(edmFunction);
var callParams = _code.StringBefore(", ",
String.Join(", ", parameters.Select(p => p.ExecuteParameterName).ToArray()));
if (includeMergeOption)
{
callParams = ", mergeOption" + callParams;
}
return string.Format(
CultureInfo.InvariantCulture,
"return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction{0}(\"{1}\"{2});",
returnType == null ? "" : "<" + _typeMapper.GetTypeName(returnType, modelNamespace) + ">",
edmFunction.Name,
callParams);
}
public string DbSet(EntitySet entitySet)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} DbSet<{1}> {2} {{ get; set; }}",
Accessibility.ForReadOnlyProperty(entitySet),
_typeMapper.GetTypeName(entitySet.ElementType),
_code.Escape(entitySet));
}
public string UsingDirectives(bool inHeader, bool includeCollections = true)
{
return inHeader == string.IsNullOrEmpty(_code.VsNamespaceSuggestion())
? string.Format(
CultureInfo.InvariantCulture,
"{0}using System;{1}" +
"{2}",
inHeader ? Environment.NewLine : "",
includeCollections
? (Environment.NewLine + "using System.Collections.Generic;")
: "",
inHeader ? "" : Environment.NewLine)
: "";
}
}
public class TypeMapper
{
private const string ExternalTypeNameAttributeName =
@"http://schemas.microsoft.com/ado/2006/04/codegeneration:ExternalTypeName";
private readonly System.Collections.IList _errors;
private readonly CodeGenerationTools _code;
private readonly MetadataTools _ef;
public TypeMapper(CodeGenerationTools code, MetadataTools ef, System.Collections.IList errors)
{
ArgumentNotNull(code, "code");
ArgumentNotNull(ef, "ef");
ArgumentNotNull(errors, "errors");
_code = code;
_ef = ef;
_errors = errors;
}
public string GetTypeName(TypeUsage typeUsage)
{
return typeUsage == null
? null
: GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
}
public string GetTypeName(EdmType edmType)
{
return GetTypeName(edmType, isNullable: null, modelNamespace: null);
}
public string GetTypeName(TypeUsage typeUsage, string modelNamespace)
{
return typeUsage == null ? null : GetTypeName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
}
public string GetTypeName(EdmType edmType, string modelNamespace)
{
return GetTypeName(edmType, isNullable: null, modelNamespace: modelNamespace);
}
public string GetTypeName(EdmType edmType, bool? isNullable, string modelNamespace)
{
if (edmType == null)
{
return null;
}
var collectionType = edmType as CollectionType;
if (collectionType != null)
{
return String.Format(CultureInfo.InvariantCulture, "ICollection<{0}>",
GetTypeName(collectionType.TypeUsage, modelNamespace));
}
var typeName = _code.Escape(edmType.MetadataProperties
.Where(p => p.Name == ExternalTypeNameAttributeName)
.Select(p => (string) p.Value)
.FirstOrDefault())
?? (modelNamespace != null && edmType.NamespaceName != modelNamespace
? _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType))
: _code.Escape(edmType));
if (edmType is StructuralType)
{
return typeName;
}
if (edmType is SimpleType)
{
var clrType = UnderlyingClrType(edmType);
if (!IsEnumType(edmType))
{
typeName = _code.Escape(clrType);
}
return clrType.IsValueType && isNullable == true
? String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName)
: typeName;
}
throw new ArgumentException("edmType");
}
public string GetInterfaceName(TypeUsage typeUsage)
{
return typeUsage == null
? null
: GetInterfaceName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace: null);
}
public string GetInterfaceName(EdmType edmType)
{
return GetInterfaceName(edmType, isNullable: null, modelNamespace: null);
}
public string GetInterfaceName(TypeUsage typeUsage, string modelNamespace)
{
return typeUsage == null
? null
: GetInterfaceName(typeUsage.EdmType, _ef.IsNullable(typeUsage), modelNamespace);
}
public string GetInterfaceName(EdmType edmType, string modelNamespace)
{
return GetInterfaceName(edmType, isNullable: null, modelNamespace: modelNamespace);
}
public string GetInterfaceName(EdmType edmType, bool? isNullable, string modelNamespace)
{
if (edmType == null)
{
return null;
}
var collectionType = edmType as CollectionType;
if (collectionType != null)
{
return String.Format(CultureInfo.InvariantCulture, "ICollection<T>",
GetInterfaceName(collectionType.TypeUsage, modelNamespace));
}
var typeName = _code.Escape(edmType.MetadataProperties
.Where(p => p.Name == ExternalTypeNameAttributeName)
.Select(p => (string) p.Value)
.FirstOrDefault())
?? (modelNamespace != null && edmType.NamespaceName != modelNamespace
? _code.CreateFullName(_code.EscapeNamespace(edmType.NamespaceName), _code.Escape(edmType))
: _code.Escape(edmType));
if (edmType is StructuralType)
{
return "T";
}
if (edmType is SimpleType)
{
var clrType = UnderlyingClrType(edmType);
if (!IsEnumType(edmType))
{
typeName = _code.Escape(clrType);
}
return clrType.IsValueType && isNullable == true
? String.Format(CultureInfo.InvariantCulture, "Nullable<{0}>", typeName)
: typeName;
}
throw new ArgumentException("edmType");
}
public Type UnderlyingClrType(EdmType edmType)
{
ArgumentNotNull(edmType, "edmType");
var primitiveType = edmType as PrimitiveType;
if (primitiveType != null)
{
return primitiveType.ClrEquivalentType;
}
if (IsEnumType(edmType))
{
return GetEnumUnderlyingType(edmType).ClrEquivalentType;
}
return typeof (object);
}
public object GetEnumMemberValue(MetadataItem enumMember)
{
ArgumentNotNull(enumMember, "enumMember");
var valueProperty = enumMember.GetType().GetProperty("Value");
return valueProperty == null ? null : valueProperty.GetValue(enumMember, null);
}
public string GetEnumMemberName(MetadataItem enumMember)
{
ArgumentNotNull(enumMember, "enumMember");
var nameProperty = enumMember.GetType().GetProperty("Name");
return nameProperty == null ? null : (string) nameProperty.GetValue(enumMember, null);
}
public System.Collections.IEnumerable GetEnumMembers(EdmType enumType)
{
ArgumentNotNull(enumType, "enumType");
var membersProperty = enumType.GetType().GetProperty("Members");
return membersProperty != null
? (System.Collections.IEnumerable) membersProperty.GetValue(enumType, null)
: Enumerable.Empty<MetadataItem>();
}
public bool EnumIsFlags(EdmType enumType)
{
ArgumentNotNull(enumType, "enumType");
var isFlagsProperty = enumType.GetType().GetProperty("IsFlags");
return isFlagsProperty != null && (bool) isFlagsProperty.GetValue(enumType, null);
}
public bool IsEnumType(GlobalItem edmType)
{
ArgumentNotNull(edmType, "edmType");
return edmType.GetType().Name == "EnumType";
}
public PrimitiveType GetEnumUnderlyingType(EdmType enumType)
{
ArgumentNotNull(enumType, "enumType");
return (PrimitiveType) enumType.GetType().GetProperty("UnderlyingType").GetValue(enumType, null);
}
public string CreateLiteral(object value)
{
if (value == null || value.GetType() != typeof (TimeSpan))
{
return _code.CreateLiteral(value);
}
return string.Format(CultureInfo.InvariantCulture, "new TimeSpan({0})", ((TimeSpan) value).Ticks);
}
public bool VerifyCaseInsensitiveTypeUniqueness(IEnumerable<string> types, string sourceFile)
{
ArgumentNotNull(types, "types");
ArgumentNotNull(sourceFile, "sourceFile");
var hash = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
if (types.Any(item => !hash.Add(item)))
{
_errors.Add(
new CompilerError(sourceFile, -1, -1, "6023",
String.Format(CultureInfo.CurrentCulture,
GetResourceString("Template_CaseInsensitiveTypeConflict"))));
return false;
}
return true;
}
public IEnumerable<SimpleType> GetEnumItemsToGenerate(IEnumerable<GlobalItem> itemCollection)
{
return GetItemsToGenerate<SimpleType>(itemCollection)
.Where(e => IsEnumType(e));
}
public IEnumerable<T> GetItemsToGenerate<T>(IEnumerable<GlobalItem> itemCollection) where T : EdmType
{
return itemCollection
.OfType<T>()
.Where(i => !i.MetadataProperties.Any(p => p.Name == ExternalTypeNameAttributeName))
.OrderBy(i => i.Name);
}
public IEnumerable<string> GetAllGlobalItems(IEnumerable<GlobalItem> itemCollection)
{
return itemCollection
.Where(i => i is EntityType || i is ComplexType || i is EntityContainer || IsEnumType(i))
.Select(g => GetGlobalItemName(g));
}
public string GetGlobalItemName(GlobalItem item)
{
if (item is EdmType)
{
return ((EdmType) item).Name;
}
else
{
return ((EntityContainer) item).Name;
}
}
public IEnumerable<EdmProperty> GetSimpleProperties(EntityType type)
{
return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
}
public IEnumerable<EdmProperty> GetSimpleProperties(ComplexType type)
{
return type.Properties.Where(p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type);
}
public IEnumerable<EdmProperty> GetComplexProperties(EntityType type)
{
return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
}
public IEnumerable<EdmProperty> GetComplexProperties(ComplexType type)
{
return type.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == type);
}
public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(EntityType type)
{
return
type.Properties.Where(
p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
}
public IEnumerable<EdmProperty> GetPropertiesWithDefaultValues(ComplexType type)
{
return
type.Properties.Where(
p => p.TypeUsage.EdmType is SimpleType && p.DeclaringType == type && p.DefaultValue != null);
}
public IEnumerable<NavigationProperty> GetNavigationProperties(EntityType type)
{
return type.NavigationProperties.Where(np => np.DeclaringType == type);
}
public IEnumerable<NavigationProperty> GetCollectionNavigationProperties(EntityType type)
{
return
type.NavigationProperties.Where(
np =>
np.DeclaringType == type &&
np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many);
}
public FunctionParameter GetReturnParameter(EdmFunction edmFunction)
{
ArgumentNotNull(edmFunction, "edmFunction");
var returnParamsProperty = edmFunction.GetType().GetProperty("ReturnParameters");
return returnParamsProperty == null
? edmFunction.ReturnParameter
: ((IEnumerable<FunctionParameter>) returnParamsProperty.GetValue(edmFunction, null)).FirstOrDefault();
}
public bool IsComposable(EdmFunction edmFunction)
{
ArgumentNotNull(edmFunction, "edmFunction");
var isComposableProperty = edmFunction.GetType().GetProperty("IsComposableAttribute");
return isComposableProperty != null && (bool) isComposableProperty.GetValue(edmFunction, null);
}
public IEnumerable<FunctionImportParameter> GetParameters(EdmFunction edmFunction)
{
return FunctionImportParameter.Create(edmFunction.Parameters, _code, _ef);
}
public TypeUsage GetReturnType(EdmFunction edmFunction)
{
var returnParam = GetReturnParameter(edmFunction);
return returnParam == null ? null : _ef.GetElementType(returnParam.TypeUsage);
}
public bool GenerateMergeOptionFunction(EdmFunction edmFunction, bool includeMergeOption)
{
var returnType = GetReturnType(edmFunction);
return !includeMergeOption && returnType != null &&
returnType.EdmType.BuiltInTypeKind == BuiltInTypeKind.EntityType;
}
}
public class EdmMetadataLoader
{
private readonly IDynamicHost _host;
private readonly System.Collections.IList _errors;
public EdmMetadataLoader(IDynamicHost host, System.Collections.IList errors)
{
ArgumentNotNull(host, "host");
ArgumentNotNull(errors, "errors");
_host = host;
_errors = errors;
}
public IEnumerable<GlobalItem> CreateEdmItemCollection(string sourcePath)
{
ArgumentNotNull(sourcePath, "sourcePath");
if (!ValidateInputPath(sourcePath))
{
return new EdmItemCollection();
}
var schemaElement = LoadRootElement(_host.ResolvePath(sourcePath));
if (schemaElement != null)
{
using (var reader = schemaElement.CreateReader())
{
IList<EdmSchemaError> errors;
var itemCollection = MetadataItemCollectionFactory.CreateEdmItemCollection(new[] {reader},
out errors);
ProcessErrors(errors, sourcePath);
return itemCollection;
}
}
return new EdmItemCollection();
}
public string GetModelNamespace(string sourcePath)
{
ArgumentNotNull(sourcePath, "sourcePath");
if (!ValidateInputPath(sourcePath))
{
return string.Empty;
}
var model = LoadRootElement(_host.ResolvePath(sourcePath));
if (model == null)
{
return string.Empty;
}
var attribute = model.Attribute("Namespace");
return attribute != null ? attribute.Value : "";
}
private bool ValidateInputPath(string sourcePath)
{
if (sourcePath == "$" + "edmxInputFile" + "$")
{
_errors.Add(
new CompilerError(_host.TemplateFile ?? sourcePath, 0, 0, string.Empty,
GetResourceString("Template_ReplaceVsItemTemplateToken")));
return false;
}
return true;
}
public XElement LoadRootElement(string sourcePath)
{
ArgumentNotNull(sourcePath, "sourcePath");
var root = XElement.Load(sourcePath, LoadOptions.SetBaseUri | LoadOptions.SetLineInfo);
return root.Elements()
.Where(e => e.Name.LocalName == "Runtime")
.Elements()
.Where(e => e.Name.LocalName == "ConceptualModels")
.Elements()
.Where(e => e.Name.LocalName == "Schema")
.FirstOrDefault()
?? root;
}
private void ProcessErrors(IEnumerable<EdmSchemaError> errors, string sourceFilePath)
{
foreach (var error in errors)
{
_errors.Add(
new CompilerError(
error.SchemaLocation ?? sourceFilePath,
error.Line,
error.Column,
error.ErrorCode.ToString(CultureInfo.InvariantCulture),
error.Message)
{
IsWarning = error.Severity == EdmSchemaErrorSeverity.Warning
});
}
}
public bool IsLazyLoadingEnabled(EntityContainer container)
{
string lazyLoadingAttributeValue;
var lazyLoadingAttributeName = MetadataConstants.EDM_ANNOTATION_09_02 + ":LazyLoadingEnabled";
bool isLazyLoading;
return !MetadataTools.TryGetStringMetadataPropertySetting(container, lazyLoadingAttributeName,
out lazyLoadingAttributeValue)
|| !bool.TryParse(lazyLoadingAttributeValue, out isLazyLoading)
|| isLazyLoading;
}
}
public static void ArgumentNotNull<T>(T arg, string name) where T : class
{
if (arg == null)
{
throw new ArgumentNullException(name);
}
}
private static readonly Lazy<System.Resources.ResourceManager> ResourceManager =
new Lazy<System.Resources.ResourceManager>(
() =>
new System.Resources.ResourceManager("System.Data.Entity.Design",
typeof (MetadataItemCollectionFactory).Assembly), isThreadSafe: true);
public static string GetResourceString(string resourceName)
{
ArgumentNotNull(resourceName, "resourceName");
return ResourceManager.Value.GetString(resourceName, null);
}
#>
public class Program
{
private static void Main()
{
var list = new List<IQueryable<Person>>();
var personQueryable = new List<Person>
{
new Person()
{
Addresses = new List<Address>()
{
new Address() {Line1 = "thing", Person = new Person()}
},
Name = "otherthing",
Address = new Address() {Line1 = "newthing", Person = new Person(){}}
}
}.AsQueryable().ToList();
list.Add(personQueryable.AsQueryable());
for (int i = 1; i < 6000; i++)
{
list.Add(new List<Person>
{
new Person()
{
Addresses = new List<Address>()
{
new Address() {Line1 = "thing", Person = new Person()}
},
Name = "otherthing",
Address = new Address() {Line1 = "newthing", Person = new Person() {}}
}
}.AsQueryable());
list.Last().First().Address.Person = list.Last().First();
}
List<List<PersonPoco>> qList = new List<List<PersonPoco>>();
personQueryable.First().Addresses.Add(personQueryable.First().Address);
personQueryable.First().Address.Person = personQueryable.First();
var tDict = new Dictionary<int, int>();
var assign = tDict[1] = 1;
var thingy =
personQueryable.Select(z => (z == null) ? z.Address : null);
//new VisualizerDevelopmentHost(thingy.Expression, typeof(ExpressionTreeVisualizer),typeof(ExpressionTreeObjectSource)).ShowVisualizer();
Stopwatch x = Stopwatch.StartNew();
Parallel.ForEach(list, (i) =>
qList.Add(i.CopyTo<Person, PersonPoco>().ToList())
);
var count = qList.Select(z => z.First().Address.Person).Distinct().Count();
x.Stop();
var t1 = x.ElapsedMilliseconds;
x = Stopwatch.StartNew();
var people = personQueryable.CopyTo<Person, PersonPoco>().ToList();
x.Stop();
var t2 = x.ElapsedMilliseconds;
var pq = personQueryable.ToList();
people = pq.CopyTo<Person, PersonPoco>().ToList();
x.Stop();
var t3 = x.ElapsedMilliseconds;
x = Stopwatch.StartNew();
people = pq.CopyTo<Person, PersonPoco>().ToList();
x.Stop();
var tAdd = people.First().Address;
var vAdd = people.First().Addresses;
var t4 = x.ElapsedMilliseconds;
Console.WriteLine(personQueryable.First());
}
}
public interface IPerson : IEntity
{
}
public interface IPerson_Name : IPerson, IEntityProperty
{
String Name { get; set; }
}
public interface IPerson_Addresses : IPerson, IEntityCollection
{
}
public interface IPerson_Addresses<T> : IPerson_Addresses
where T : IAddress, new()
{
ICollection<T> Addresses { get; set; }
}
public interface IPerson_Address : IPerson, IEntityObject
{
}
public interface IPerson_Address<T> : IPerson_Address
where T : IAddress, new()
{
T Address { get; set; }
}
public class Person : IPerson_Name, IPerson_Addresses<Address>, IPerson_Address<Address>, IAddress
{
public String Name { get; set; }
public ICollection<Address> Addresses { get; set; }
public Address Address { get; set; }
}
public class PersonPoco : IPerson_Name, IPerson_Addresses<AddressPoco>, IPerson_Address<AddressPoco>
{
public string Name { get; set; }
public ICollection<AddressPoco> Addresses { get; set; }
public AddressPoco Address { get; set; }
}
public interface IAddress : IEntity
{
}
public interface IAddress_Line1 : IAddress, IEntityProperty
{
String Line1 { get; set; }
}
public interface IAddress_Person : IAddress, IEntityObject
{
}
public interface IAddress_Person<T> : IAddress_Person
where T : IPerson, new()
{
T Person { get; set; }
}
public class Address : IAddress_Line1, IAddress_Person<Person>
{
public String Line1 { get; set; }
public Person Person { get; set; }
}
public class AddressPoco : IAddress_Line1, IAddress_Person<PersonPoco>
{
public String Line1 { get; set; }
public PersonPoco Person { get; set; }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment