实体框架IQueryable与poco生成 [英] Entity framework IQueryable with poco generation

查看:122
本文介绍了实体框架IQueryable与poco生成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个T4模板,它为每个属性生成标准的Entities类以及Interfaces,以便我可以使仅包含我想要的数据的自定义poco对象。我还创建了一个复制功能,可以在实现所述实体接口的任何对象之间进行转换。



生成的代码看起来像这样

  // -------------------------------- ---------------------------------------------- 
//< auto-generated>
//该代码是从模板生成的。
//
//手动更改此文件可能会导致应用程序出现意外的行为。
//如果重新生成代码,则对该文件的手动更改将被覆盖。
//< / auto-generated>
// -------------------------------------------- ----------------------------------

命名空间DomainModel
{
使用系统;
使用System.Collections.Generic;
使用System.Linq;


public interface IRole
{
}
public interface IRole_RoleId:IRole
{
int RoleId {get;组; }
}
public interface IRole_ApplicationName:IRole
{
string ApplicationName {get;组;
}
public interface IRole_RoleName:IRole
{
string RoleName {get;组;
}
public interface IRole_Description:IRole
{
string描述{get;组; }
}

public interface IRole_Users:IRole
{
ICollection< IUser>用户{get;组; }
IUser NewUsers();
}

public interface IRole__All:IRole_RoleId,
IRole_ApplicationName,
IRole_RoleName,
IRole_Description,
IRole_Users
{


public partial class角色:IRole
{
public Role()
{
this.Users = new HashSet< User>();
}

public int RoleId {get;组; }
public string ApplicationName {get;组; }
public string RoleName {get;组; }
public string描述{get;组; }

public virtual ICollection< User>用户{get;组;
}

public static class IRoleExt
{
public static T CopyTo< T>(此IRole src,T dest = null)其中T:class,IRole ,new()
{
dest = dest ??新T();
dest.Copy(src);
return dest;
}
public static void复制(此IRole dest,IRole src)
{
var ms = new MergeStack();
角色角色;
if((role = dest as Role)!= null){
ms.TryCopy< IRole,Role>((indexCopy)=> {return indexCopy(role);},src);
}
else if((role = src as Role)!= null){
ms.TryCopy< Role,IRole>((indexCopy)=> {return indexCopy(dest) },角色);
}
else {
ms.TryCopy< IRole,IRole>((indexCopy)=> {return indexCopy(dest);},src);
}
dest.Copy(src,ms);
}

内部静态void复制(此IRole dest,
IRole src,
MergeStack ms)
{
dest.Set_RoleId(src .Get_RoleId());
dest.Set_ApplicationName(src.Get_ApplicationName());
dest.Set_RoleName(src.Get_RoleName());
dest.Set_Description(src.Get_Description());
dest.Set_Users(src.Get_Users(),ms);
}
public static Nullable< int> Get_RoleId(this IRole src)
{
IRole_RoleId srcIRole_RoleId;
if((srcIRole_RoleId = src as IRole_RoleId)!= null)
{
return srcIRole_RoleId.RoleId;
}
角色角色;
if((role = src as Role)!= null)
{
return role.RoleId;
}
返回null;

}
public static void Set_RoleId(此IRole dest,Nullable< int> src)
{
IRole_RoleId destIRole_RoleId;
if((destIRole_RoleId = dest as IRole_RoleId)!= null)
{
destIRole_RoleId.RoleId = src.GetValueOrDefault();
}
角色角色;
if((role = dest as Role)!= null)
{
role.RoleId = src.GetValueOrDefault();
}
}

public static string Get_ApplicationName(此IRole src)
{
IRole_ApplicationName srcIRole_ApplicationName;
if((srcIRole_ApplicationName = src as IRole_ApplicationName)!= null)
{
return srcIRole_ApplicationName.ApplicationName;
}
角色角色;
if((role = src as Role)!= null)
{
return role.ApplicationName;
}
返回null;

}
public static void Set_ApplicationName(此IRole dest,string src)
{
IRole_ApplicationName destIRole_ApplicationName;
if((destIRole_ApplicationName = dest as IRole_ApplicationName)!= null)
{
destIRole_ApplicationName.ApplicationName = src;
}
角色角色;
if((role = dest as Role)!= null)
{
role.ApplicationName = src;
}
}

public static string Get_RoleName(this IRole src)
{
IRole_RoleName srcIRole_RoleName;
if((srcIRole_RoleName = src as IRole_RoleName)!= null)
{
return srcIRole_RoleName.RoleName;
}
角色角色;
if((role = src as Role)!= null)
{
return role.RoleName;
}
返回null;

}
public static void Set_RoleName(此IRole dest,string src)
{
IRole_RoleName destIRole_RoleName;
if((destIRole_RoleName = dest as IRole_RoleName)!= null)
{
destIRole_RoleName.RoleName = src;
}
角色角色;
if((role = dest as Role)!= null)
{
role.RoleName = src;
}
}

public static string Get_Description(this IRole src)
{
IRole_Description srcIRole_Description;
if((srcIRole_Description = src as IRole_Description)!= null)
{
return srcIRole_Description.Description;
}
角色角色;
if((role = src as Role)!= null)
{
return role.Description;
}
返回null;

}
public static void Set_Description(此IRole dest,string src)
{
IRole_Description destIRole_Description;
if((destIRole_Description = dest as IRole_Description)!= null)
{
destIRole_Description.Description = src;
}
角色角色;
if((role = dest as Role)!= null)
{
role.Description = src;
}
}

public static ICollection< IUser> Get_Users(this Role src)
{
return src.Users.Cast< IUser>()。ToList();
}
public static ICollection< IUser> Get_Users(this IRole src)
{
IRole_Users srcIRole_Users;
if((srcIRole_Users = src as IRole_Users)!= null)
{
return srcIRole_Users.Users;
}
角色角色;
if((role = src as Role)!= null)
{
return role.Get_Users();
}
返回null;
}
public static void Set_Users(此IRole dest,ICollection< IUser> src)
{
var ms = new MergeStack();
dest.Set_Users(src,ms);
}

内部静态void Set_Users(此IRole dest,ICollection< IUser> src,MergeStack ms)
{
IRole_Users destIRole_Users;
if((destIRole_Users = dest as IRole_Users)!= null)
{
Func< IUser,IUser> iToIFunc =(x =>
ms.TryCopy< IUser,IUser>((indexCopy)=>
{
var ret = destIRole_Users.NewUsers();
var exists = indexCopy(ret);
if(null!= exists)
ret = exists;
else
ret.Copy(x,ms);
return ret;
},x));
destIRole_Users.Users =(null!= src)?
src.Select(iToIFunc).ToList():null;
}

角色角色;
if((role = dest as Role)!= null)
{
Func< IUser,User> iToEFunc =(x =>
ms.TryCopy< IUser,User>((indexCopy)=>
{
var ret = new User();
var exists = indexCopy(ret);
if(null!= exists)
ret = exists;
else
ret.Copy(x,ms);
return ret;
},x));
role.Users =(null!= src)?
src.Select(iToEFunc).ToList():null;
}
}
}
}

合并堆栈对象你看到的是一个跟踪器,所以我可以处理引用循环。看起来像这样

  using System; 
使用System.Collections.Generic;
使用System.Linq;

命名空间DomainModel
{

内部类MergeStack
{
私有只读字典<类型,字典< Object,Object>> _mergeObjDict = new Dictionary< Type,Dictionary< object,object>>();
private readonly IList< Action> _registerActions = new List< Action>();

public T TryCopy< TKey,T>(Func< Func< T,T> T> func,TKey key)其中T:class
{
if(key = = null)
返回null;

Func< T,T> act =(objToIndex)=>
{
字典< 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(key))
{
objToObj.Add(key,objToIndex);
}
else
{
return objToObj [key] as T;
}
返回null作为T;
};
return func(act);
}
}
}

现在这一切都可以正常工作意图,它成功地将所有实现的属性复制到域模型/界面。



我现在正在尝试使用IQueryable和懒惰加载播放。 p>

现在我正在这样做

  dbContext.Roles.Select (x)=> x.CopyTo&RolesPoco>()); 

我想看看有没有办法自动生成包括如

  dbContext.Roles.Select((x)=> x.Users.Include((y)=> y.someSubEntity); 

我也想看看是否可以放在这样一些这样的条款

  //第一个字符串是一个路径,像Roles.Users.someSubEntity
//第二个字符串是一个IQueryable函数例如Where or Take
Dictionary< String,Dictionary< String,List&FunC< T,IQueryable< TProperty>>>>>       => x.CopyTo&RolesPoco>(queryDict)

然后列表将是一些列表可以在include函数中运行的lambdas
任何人都有任何想法?



编辑:我重构了一些代码,以便它可以调用一个getter / setter即使该类没有impl接口。所以属性可以被访问,无论是否有一个后备字段。如果没有定义,它返回null。



Edit2 :由于我想要达到的目标似乎不清楚,让我澄清一下。如果您参考 msdn的备注部分页面,您将看到一些select语句。我想生成这些表达式,然后根据被复制的类是否包含实现该成员的接口,在父选择之内使用它们。我避免使用linqToObject,因为我只需要在CopyTo中定义的属性,但是Navigation属性就是接口,它会破坏实体框架。这是为了懒惰加载的目的。 MergeStack将组合并将这些表达式返回到树中。我得到了一个DaedTech博客的想法>

解决方案

角色是IQueryable,所以你需要从Queryable extensions类获取Select方法。
您还需要从Enumerable扩展类中获取Include。
然后,您需要使用Role作为通用参数来调用Select方法。
您需要使用Expression.Lambda,Expression.Call和Expression.Property构造一个lambda。


I've created a T4 template which generates standard Entities classes along with Interfaces for each of their properties so that I can make customized poco objects containing only the data that I want. I've also created a copy function which can convert between any of the objects which implement said entity's interface

The generated code looks like this

//------------------------------------------------------------------------------
// <auto-generated>
//    This code was generated from a template.
//
//    Manual changes to this file may cause unexpected behavior in your application.
//    Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace DomainModel
{
    using System;
    using System.Collections.Generic;
    using System.Linq;


    public interface IRole
    {
    }
    public interface IRole_RoleId : IRole
    {
      int RoleId { get; set; }
    }
    public interface IRole_ApplicationName : IRole
    {
      string ApplicationName { get; set; }
    }
    public interface IRole_RoleName : IRole
    {
      string RoleName { get; set; }
    }
    public interface IRole_Description : IRole
    {
      string Description { get; set; }
    }

    public interface IRole_Users : IRole 
    {
      ICollection<IUser> Users { get; set; }
      IUser NewUsers();
    }

    public interface IRole__All : IRole_RoleId, 
      IRole_ApplicationName, 
      IRole_RoleName, 
      IRole_Description, 
      IRole_Users
    {
    }

    public partial class Role : IRole
    {
      public Role()
      {
        this.Users = new HashSet<User>();
      }

      public int RoleId { get; set; }
      public string ApplicationName { get; set; }
      public string RoleName { get; set; }
      public string Description { get; set; }

      public virtual ICollection<User> Users { get; set; }
    }

    public static class IRoleExt
    {
      public static T CopyTo<T>(this IRole src , T dest = null  )  where T : class, IRole, new()
      {
        dest = dest ?? new T();
        dest.Copy(src);
        return dest;
      }
      public static void Copy(this IRole dest, IRole src)
      {
        var ms = new MergeStack();
        Role role;
        if((role = dest as Role) != null){
          ms.TryCopy<IRole,Role>((indexCopy) => {return indexCopy(role);}, src);
        }
        else if ((role = src as Role) != null){
          ms.TryCopy<Role,IRole>((indexCopy) => {return indexCopy(dest);}, role);
        }
        else{
          ms.TryCopy<IRole,IRole>((indexCopy) => {return indexCopy(dest);}, src);
        }
        dest.Copy(src, ms);
      }

      internal static void Copy(this IRole dest,
        IRole src,
        MergeStack ms)
      {
        dest.Set_RoleId(src.Get_RoleId());
        dest.Set_ApplicationName(src.Get_ApplicationName());
        dest.Set_RoleName(src.Get_RoleName());
        dest.Set_Description(src.Get_Description());
        dest.Set_Users(src.Get_Users(),ms);
      }
        public static Nullable<int> Get_RoleId(this IRole src)
      {
        IRole_RoleId srcIRole_RoleId;
        if((srcIRole_RoleId = src as IRole_RoleId) != null )
        {
          return srcIRole_RoleId.RoleId;
        }
        Role role;
        if((role = src as Role) != null )
        {
          return role.RoleId;
        }
          return null;

      }
        public static void Set_RoleId(this IRole dest, Nullable<int> src)
      {
        IRole_RoleId destIRole_RoleId;
        if((destIRole_RoleId = dest as IRole_RoleId) != null)
        {
           destIRole_RoleId.RoleId = src.GetValueOrDefault();
            }
        Role role;
        if((role = dest as Role) != null )
        {
          role.RoleId = src.GetValueOrDefault();
        }
      }

        public static string Get_ApplicationName(this IRole src)
      {
        IRole_ApplicationName srcIRole_ApplicationName;
        if((srcIRole_ApplicationName = src as IRole_ApplicationName) != null )
        {
          return srcIRole_ApplicationName.ApplicationName;
        }
        Role role;
        if((role = src as Role) != null )
        {
          return role.ApplicationName;
        }
          return null;

      }
        public static void Set_ApplicationName(this IRole dest, string src)
      {
        IRole_ApplicationName destIRole_ApplicationName;
        if((destIRole_ApplicationName = dest as IRole_ApplicationName) != null)
        {
           destIRole_ApplicationName.ApplicationName = src;
            }
        Role role;
        if((role = dest as Role) != null )
        {
          role.ApplicationName = src;
        }
      }

        public static string Get_RoleName(this IRole src)
      {
        IRole_RoleName srcIRole_RoleName;
        if((srcIRole_RoleName = src as IRole_RoleName) != null )
        {
          return srcIRole_RoleName.RoleName;
        }
        Role role;
        if((role = src as Role) != null )
        {
          return role.RoleName;
        }
          return null;

      }
        public static void Set_RoleName(this IRole dest, string src)
      {
        IRole_RoleName destIRole_RoleName;
        if((destIRole_RoleName = dest as IRole_RoleName) != null)
        {
           destIRole_RoleName.RoleName = src;
            }
        Role role;
        if((role = dest as Role) != null )
        {
          role.RoleName = src;
        }
      }

        public static string Get_Description(this IRole src)
      {
        IRole_Description srcIRole_Description;
        if((srcIRole_Description = src as IRole_Description) != null )
        {
          return srcIRole_Description.Description;
        }
        Role role;
        if((role = src as Role) != null )
        {
          return role.Description;
        }
          return null;

      }
        public static void Set_Description(this IRole dest, string src)
      {
        IRole_Description destIRole_Description;
        if((destIRole_Description = dest as IRole_Description) != null)
        {
           destIRole_Description.Description = src;
            }
        Role role;
        if((role = dest as Role) != null )
        {
          role.Description = src;
        }
      }

      public static ICollection<IUser> Get_Users(this Role src)
      {
        return src.Users.Cast<IUser>().ToList();
        }
        public static ICollection<IUser> Get_Users(this IRole src)
      {
        IRole_Users srcIRole_Users;
        if((srcIRole_Users = src as IRole_Users) != null )
        {
          return srcIRole_Users.Users;
        }
        Role role;
        if((role = src as Role) != null )
        {
          return role.Get_Users();
        }
          return null;
      }
      public static void Set_Users(this IRole dest, ICollection<IUser> src)
      {
        var ms = new MergeStack();
        dest.Set_Users(src, ms);
      }

      internal static void Set_Users(this IRole dest, ICollection<IUser> src, MergeStack ms)
      {
        IRole_Users destIRole_Users;
        if((destIRole_Users = dest as IRole_Users) != null)
        {
          Func<IUser,IUser> iToIFunc = (x=> 
              ms.TryCopy<IUser,IUser>((indexCopy)=>
              {
                var ret = destIRole_Users.NewUsers();
                  var exists = indexCopy(ret);
                if(null != exists)
                    ret = exists;
                  else
                  ret.Copy(x,ms);
                return ret;
              },x));
          destIRole_Users.Users = (null !=src)?
          src.Select(iToIFunc).ToList():null;
        }

        Role role;
        if((role = dest as Role) != null)
        {
          Func<IUser,User> iToEFunc = (x=> 
              ms.TryCopy<IUser,User>((indexCopy)=>
              {
                var ret = new User();
                  var exists = indexCopy(ret);
                if(null != exists)
                    ret = exists;
                  else
                  ret.Copy(x,ms);
                return ret;
              },x));
          role.Users = (null !=src)?
          src.Select(iToEFunc).ToList():null;
        }
      }
    }
}

That merge stack object you see is a tracker so I can handler reference loops. it looks like this

using System;
using System.Collections.Generic;
using System.Linq;

namespace DomainModel
{

    internal class MergeStack
    {
        private readonly Dictionary<Type, Dictionary<Object, Object>> _mergeObjDict = new Dictionary<Type, Dictionary<object, object>>();
        private readonly IList<Action> _registerActions = new List<Action>();

        public T TryCopy<TKey, T>(Func<Func<T, T>, T> func, TKey key) where T : class
        {
            if (key == null)
                return null;

            Func<T, T> act = (objToIndex) =>
            {
                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(key))
                {
                    objToObj.Add(key, objToIndex);
                }
                else
                {
                    return objToObj[key] as T;
                }
                return null as T;
            };
            return func(act);
        }
    }
}

Now all this works fine as intended, it successfully copies over all implemented properties to and from the domain model/interface.

I'm now trying to make play nice with IQueryable and lazy loading.

Right now I'm doing this

dbContext.Roles.Select((x)=> x.CopyTo<RolesPoco>());

I'd like to see if there's a way I could auto generate includes such as

dbContext.Roles.Select((x)=> x.Users.Include((y)=> y.someSubEntity);

I'd also like to see if I could put on some where clauses like this

//the first string is a path so something like "Roles.Users.someSubEntity"
//the second string is a IQueryable function like Where or Take
Dictionary<String,Dictionary<String,List<Func<T, IQueryable<TProperty>>>> queryDict

dbContext.Roles.Select((x)=> x.CopyTo<RolesPoco>(queryDict)

And then the List would be some list of lambdas that can run inside of the include functions. Anybody have any ideas on this?

Edit: I refactored simplified some of the code so that it could call a getter/setter even if the class didn't implement the interface. So the properties can be accessed regardless of there being a backing field. It returns null if it's not defined.

Edit2: Since it seems unclear what I'm trying to achieve, let me clarify. If you go down to the remarks part of this msdn page, you'll see some select statements. I want to generate those Expressions and then use them inside of a parent select based on whether or not the class being copied to contains the interface that implements that member. I'm avoiding linqToObject because I only need the properties defined in the CopyTo, but the Navigation properties are interfaces, which blows up entity framework. This is for Lazy loading purposes. MergeStack would be composing and returning those expressions up the tree. I got the idea from a DaedTech blogpost

解决方案

Roles is IQueryable, so you need to get the Select method from the Queryable extensions class. You also need to get the Include from the Enumerable extension class. You then need to invoke the Select method using Role as a generic argument. You need to construct a lambda using Expression.Lambda, Expression.Call and Expression.Property.

这篇关于实体框架IQueryable与poco生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆