简体   繁体   English

实体框架IQueryable与poco生成

[英]Entity framework IQueryable with poco generation

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. 我已经创建了一个T4模板,它为每个属性生成标准的Entities类和Interfaces,这样我就可以制作只包含我想要的数据的自定义poco对象。 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. 我现在正试图用IQueryable和延迟加载来玩得很好。

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. 然后List将是一些可以在include函数内运行的lambdas列表。 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. 编辑 :我重构了一些简化的代码,以便即使类没有实现接口也可以调用getter / setter。 So the properties can be accessed regardless of there being a backing field. 因此,无论是否存在支持字段,都可以访问属性。 It returns null if it's not defined. 如果未定义,则返回null。

Edit2 : Since it seems unclear what I'm trying to achieve, let me clarify. 编辑2 :由于我似乎不清楚我想要实现的目标,让我澄清一下。 If you go down to the remarks part of this msdn page , you'll see some select statements. 如果你转到这个msdn页面的备注部分,你会看到一些select语句。 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. 我正在避免使用linqToObject,因为我只需要在CopyTo中定义的属性,但是导航属性是接口,它会炸毁实体框架。 This is for Lazy loading purposes. 这是为了延迟加载目的。 MergeStack would be composing and returning those expressions up the tree. MergeStack将组合并在树上返回这些表达式。 I got the idea from a DaedTech blogpost 我从DaedTech的博文中得到了这个想法

Roles is IQueryable, so you need to get the Select method from the Queryable extensions class. 角色是IQueryable,因此您需要从Queryable扩展类中获取Select方法。 You also need to get the Include from the Enumerable extension class. 您还需要从Enumerable扩展类中获取Include。 You then need to invoke the Select method using Role as a generic argument. 然后,您需要使用Role作为通用参数来调用Select方法。 You need to construct a lambda using Expression.Lambda, Expression.Call and Expression.Property. 您需要使用Expression.Lambda,Expression.Call和Expression.Property构造lambda。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM