EF1:使用 .OfType<> 过滤实体类的派生类型通过传递字符串值

发布于 2024-10-12 23:40:18 字数 1141 浏览 6 评论 0 原文

我遇到了一种情况,我试图使用派生子类来过滤 LINQ 选择。

ctx.BaseEntity.OfType() - 这工作正常。

不过,我想使用字符串值来完成此操作。当我有很多(> 20)子类并且不使用 OfType 选择实体时,我遇到了性能障碍。我有一个从基类呈现的通用 UI,因此我不知道在编译时将返回什么类类型。

所以我想做的是:

  1. 执行投影选择我所在的位置 仅返回子类类型 数据库
  2. 执行第二次选择 使用该值作为 OfType 来 只选择相关的相关 数据库中的实体(无质量 生成工会)

     int id = 1;
        var classType = (来自 ctx.BaseClass.Include("ClassType") 中的 c)
                                   其中 c.id == id
                                   选择新的
                                              {
                                                  c.ClassType.TypeName
                                              })。第一的();
    
        BaseClass caseQuery = ctx.BaseClass.OfType()
                        .include("类类型")
                        .include("ChildEntity1")
                        .include("ChildEntity2")
                        .Where(x => x.id== id);
    

但显然这不起作用,因为 OfType 需要类型而不是字符串

关于如何实现这一目标有什么想法吗?

更新: 作为原始问题的旁注,事实证明,当您项目使用导航属性的查询时,它也会构建怪物 SQL,因此我最终使用存储过程从 BaseClass 填充我的 ClassType 实体ID。

I have a situation where I'm trying to filter a LINQ select using a derived sub class.

ctx.BaseEntity.OfType<SubClass>() - this works fine.

However I'd like to do this using a string value instead. I've come across a performance barrier when I have lots (>20) Sub Classes and selecting an Entity without using OfType just isn't an option. I have a generic UI that renders from the base class, so I don't know what Class Type will be returned at compile time.

So what I'd like to do is this:

  1. Perform a projected Select where I
    return just the SubClassType from
    the database
  2. Perform a second select
    using this value as the OfType to
    only select the relevant related
    entity from the database (No mass
    unions generated)

        int id = 1;
        var classType = (from c in ctx.BaseClass.Include("ClassType")
                                   where c.id == id
                                   select new
                                              {
                                                  c.ClassType.TypeName
                                              }).First();
    
        BaseClass caseQuery = ctx.BaseClass.OfType<classType.TypeName>()
                        .Include("ClassType")
                        .Include("ChildEntity1")
                        .Include("ChildEntity2")
                        .Where(x => x.id== id);
    

But obviously this won't work because OfType requires a Type and not a string.

Any ideas on how I can achieve this?

Update:
As a side note to the original question, it turns out that the moment you project a query that uses a Navigation Property - it builds the monster SQL too, so I've ended up using a stored procedure to populate my ClassType entity from the BaseClass Id.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

与风相奔跑 2024-10-19 23:40:18

所以我刚刚使用 eSQL 让它工作,而我以前从未使用过它。我在这里发布了代码,以防它对某人有帮助。还有其他人有他们能想到的更强类型的解决方案吗?

BaseClass caseQuery = ctx.BaseClass.CreateQuery<BaseClass>("SELECT VALUE c FROM OFTYPE(Entities.[BaseClass],namespace.[" + classType.TypeName + "])  as c")
                .Include("ClassType")
                .Include("ChildEntity1")
                .Include("ChildEntity2")
                .Where(x => x.id== id).FirstOrDefault();

So I've just got it to work using eSQL, which I'd never used before. I've posted the code here just in case it helps someone. Has anyone else got a more strongly typed solution they can think of?

BaseClass caseQuery = ctx.BaseClass.CreateQuery<BaseClass>("SELECT VALUE c FROM OFTYPE(Entities.[BaseClass],namespace.[" + classType.TypeName + "])  as c")
                .Include("ClassType")
                .Include("ChildEntity1")
                .Include("ChildEntity2")
                .Where(x => x.id== id).FirstOrDefault();
相思故 2024-10-19 23:40:18

要回答有关使用字符串/运行时类型调用 OfType 的标题问题,您可以执行以下操作:

// Get the type, assuming the derived type is defined in the same assembly 
// as the base class and you have the type name as a string
var typeToFilter = typeof(BaseClass)
     .Assembly
     .GetType("Namespace." + derivedTypeName);

// The use reflection to get the OfType method and call it directly
MethodInfo ofType = typeof(Queryable).GetMethod("OfType");
MethodInfo ofTypeGeneric = method.MakeGenericMethod(new Type[] { typeToFilter });
var result = (IQueryable<Equipment>)generic.Invoke(null, new object[] { equipment });

将其与存储过程结合起来以获取类名,并且您(应该?)避免大量连接 -我没有每个类型的表实现可供使用,所以我无法测试。

To answer the headline question about calling OfType with a string / runtime type, you can do the following:

// Get the type, assuming the derived type is defined in the same assembly 
// as the base class and you have the type name as a string
var typeToFilter = typeof(BaseClass)
     .Assembly
     .GetType("Namespace." + derivedTypeName);

// The use reflection to get the OfType method and call it directly
MethodInfo ofType = typeof(Queryable).GetMethod("OfType");
MethodInfo ofTypeGeneric = method.MakeGenericMethod(new Type[] { typeToFilter });
var result = (IQueryable<Equipment>)generic.Invoke(null, new object[] { equipment });

Combine this with your stored procedure to get the class name and you (should?) avoid the massive join - I don't have table-per-type implementation to play with so I can't test.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文