【问题标题】:Entity Framework 6 + Oracle how to query two tables which are identical in structureEntity Framework 6 + Oracle 如何查询两个结构相同的表
【发布时间】:2016-09-02 21:30:56
【问题描述】:

我有两个结构相同的实体框架模型,它们是使用 Oracle DB 中的 Code First 生成的(2 个“双”表,请不要问为什么,我无法控制 DB)。

我一直在寻找一种使用 Linq 的有效方法,试图避免两次重写相同的查询。

一些例子:

[Table("ORACLE.TABLE1")]
public partial class MyModel1
{
    [Key]
    [Column(Order = 0)]
    [StringLength(3)]
    public string field1 { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(3)]
    public string field2 { get; set; }

    [Key]
    [Column(Order = 2)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int field3 { get; set; }

    // -- many other fields

}

[Table("ORACLE.TABLE2")]
public partial class MyModel2
{
    [Key]
    [Column(Order = 0)]
    [StringLength(3)]
    public string field1 { get; set; }

    [Key]
    [Column(Order = 1)]
    [StringLength(3)]
    public string field2 { get; set; }

    [Key]
    [Column(Order = 2)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int field3 { get; set; }

    // -- many other fields, same as above
}

在某个地方,我有:

    public virtual DbSet<MyModel1> MyModel1s { get; set; }       
    public virtual DbSet<MyModel2> MyModel2s { get; set; }

我目前获取数据的简单而丑陋的解决方案是这样的:

        var result1 = from t in db.MyModel1s
                      where t.field1 == myparameter1
                         && t.field2 == myparameter2
                         && t.field3 == myparameter3
                      select t;

        var result2 = from t in db.MyModel2s
                      where t.field1 == myparameter1
                         && t.field2 == myparameter2
                         && t.field3 == myparameter3
                      select t;
        var result = result1.ToList();

...最后...

        foreach (var res2 in result2)
        {
            var m1 = new MyModel1
            {
                field1 = res2.field1,
                field2 = res2.field2,
                field3 = res3.field3
            };
            result.Add(m1);
        }

现在result 包含我想要的所有内容。 一定有更好的方法,建议?

【问题讨论】:

    标签: c# oracle entity-framework linq


    【解决方案1】:

    你可以使用Concat扩展方法来做这样的事情,相当于SQL中的UNION ALL

        var result= db.MyModel1s.Where(m=>m.field1 == myparameter1
                                       && m.field2 == myparameter2
                                       && m.field3 == myparameter3)
                                .Select(t=>new MyModelDTO
                                          {
                                             field1 = t.field1,
                                             field2 = t.field2,
                                             field3 = t.field3
                                          }
                                       )
                                .Concat( db.MyModel2s.Where(t=> t.field1 == myparameter1
                                                             && t.field2 == myparameter2
                                                             && t.field3 == myparameter3)
                                                     .Select(t=>new MyModelDTO
                                                                {
                                                                 field1 = t.field1,
                                                                 field2 = t.field2,
                                                                 field3 = t.field3
                                                                }
                                                             )
                                       ).ToList();
    

    这样,您将在一次往返数据库的过程中获得结果。如果您想避免重复,请改用Union 扩展方法。

    现在,如果您不想将两个查询都投射到一个公共 DTO,那么您将需要对您的数据库进行两次往返并在内存中进行合并:

        var result= db.MyModel1s.Where(m=>m.field1 == myparameter1
                                       && m.field2 == myparameter2
                                       && m.field3 == myparameter3)
                                .AsEnumerable()// Calling the method you will call Concat extension method from IEnumerable<T> type
                                .Concat( db.MyModel2s.Where(t=> t.field1 == myparameter1
                                                             && t.field2 == myparameter2
                                                             && t.field3 == myparameter3)
                                                     .Select(t=>new MyModel1
                                                                {
                                                                 field1 = t.field1,
                                                                 field2 = t.field2,
                                                                 field3 = t.field3
                                                                }
                                                             )
                                       ).ToList();
    

    【讨论】:

    • 实际上,因为这个原因它不起作用:stackoverflow.com/questions/5325797/… 我无法创建 DTO,因为我无法将 DTO 与映射实体连接
    • 对,我忘了。你能用同一个 DTO 投影两个查询吗?我认为最好的解决方案是你想在服务器端执行这个查询。否则,您将需要对数据库执行两次往返并将两个结果合并到内存中。您可以使用AsEnumerable 扩展方法在一个查询中做到这一点,您需要关于最后一个想法的帮助吗?
    • 我想我应该按照 Remus 的建议向 DBA 询问视图的创建,否则是的,我需要关于你最后一个想法的帮助。
    • 好的,在这种情况下,试试我的第二个查询;)
    • 那么在这种情况下,您可以分几个步骤构建查询,最后您可以通过以下方式实现它们:var result=query1.AsEnumerable().Concat(query2).ToList();
    【解决方案2】:

    在数据库中创建一个在两个表之间执行 UNION ALL 的视图,然后改为查询该视图。 做联合客户端,你会错过可能的服务器端优化,你将无法提供某些语义,如跨两个表的正确顺序。

    【讨论】:

    • 修改表结构,或者要求应用只使用一个表,现在这将是一个的变化。声明一个视图,没那么多。
    • 如果我无法控制,每一个变化都可能是“很多” :) 无论如何谢谢
    猜你喜欢
    • 2020-05-07
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 1970-01-01
    • 2015-11-09
    相关资源
    最近更新 更多