7

我有一个基类和两个派生类。

每个派生类都实现了与属性相同的类型——唯一的区别是属性名称。

遗憾的是,我对类设计没有太大影响-> 它们是从 wsdl 文件生成的。

然后我在 BaseType 上有一个属性来封装公共属性。计划是在我的网络视图等中使用这个属性。

我用著名的“水果示例”来演示这个问题:

 public class FruitBase
    {
        public virtual int ID { get; set; }


        //
        // The plan is to use this property in mvc view
        //
        [NotMapped]
        public virtual FruitnessFactor Fruitness
        {
            get
            {
                if (this.GetType().BaseType == typeof(Apple))
                    return ((Apple)this).AppleFruitness;
                else if (this.GetType().BaseType == typeof(Orange))
                    return ((Orange)this).OrangeFruitness;
                else
                    return null;
            }
        }
    }

public class FruitnessFactor { }

在我的 MVC 控制器中,以下查询绝对可以正常工作:

return View(context.FruitEntities
                           .OfType<Apple>().Include(a =>a.AppleFruitness)
                           .ToList());

但是这个没有:

  return View(context.FruitEntities
                                   .OfType<Apple>().Include(a =>a.AppleFruitness)
                                   .OfType<Orange>().Include(o => o.OrangeFruitness)
                                   .ToList());

我得到的错误信息是:

DbOfTypeExpression 需要具有与类型参数兼容的多态结果类型的表达式参数。

我正在使用 EF 5.0 RC 和 Code First 方法。

任何帮助深表感谢!

4

1 回答 1

9

据我所知,您不能Include在单个数据库查询中应用多个子类型。您可以查询一种类型 ( OfType<Apple>().Include(a => a.AppelFruitness)) 并为另一种子类型查询相同的类型。问题是您不能在同一个查询中连接结果,因为结果集合具有不同的泛型类型(苹果和橙子)。

一种选择是运行两个查询并将结果集合复制到基本类型的新集合中 - 正如您已经在问题下的评论部分中指出的那样。

另一个选项(只需要一个查询)是投影。你必须定义一个投影类型(你也可以投影到一个匿名类型)......

public class FruitViewModel
{
    public FruitBase Fruit { get; set; }
    public FruitnessFactor Factor { get; set; }
}

...然后可以使用查询:

List<FruitViewModel> fruitViewModels = context.FruitEntities
    .OfType<Apple>()
    .Select(a => new FruitViewModel
    {
        Fruit = a,
        Factor = a.AppleFruitness
    })
    .Concat(context.FruitEntities
    .OfType<Orange>()
    .Select(o => new FruitViewModel
    {
        Fruit = o,
        Factor = o.OrangeFruitness
    }))
    .ToList();

如果您不禁用更改跟踪(通过使用AsNoTracking),导航属性会在实体附加到上下文(“关系修复”)时自动填充,这意味着您可以从 viewModel 集合中提取结果......

IEnumerable<FruitBase> fruits = fruitViewModels.Select(fv => fv.Fruit);

...您将获得包括FruitnessFactor属性在内的果实。

这段代码非常尴尬,但是已经多次询问了不使用投影的直接方法,但均未成功:

于 2012-06-14T19:29:36.443 回答