实体框架返回两个表的连接的IQueryable

时间:2017-02-15 17:36:10

标签: c# linq entity-framework-6

我想使用Entity Framework从2个表中返回数据,并选择2个表中的列,起初我对简单的事情没什么好运,比如返回int和字符串(即。{{ 1}},因为在目的地(目的地是我的winform)上,匿名类型很麻烦,所以我想到了只返回两个表行...

这样的事情:

select new { id = t1.ID, other = t2.OtherData }

这一切都很好除了方法的返回类型不正确。我试过几个组合。不幸的是,当我从winform调用“byRecID”时,“SingleOrDefault”不可用,但是在'byRecID'方法中可以使用IS,所以我不能只返回 public static IQueryable<{Table1,Table2}> byRecID(Guid recID, MyContext DBContext) { return (from i1 in DBContext.Table1 join j1 in DBContext.Table2 on i1.GroupID equals j1.GroupID where i1.RecID.Equals(RecID) select new { i1, j1 }).SingleOrDefault(); } ,需要输入IQueryable (因为IQueryable<SOMETHING IN HERE>不是SingleOrDefault的扩展名,只有IQueryable)。

我的问题......是否有一个'SOMETHING IN HERE'的语法,可以让我指定它的两个表行的连接?

我想知道......为什么SingleOrDefault是一个选项INSIDE方法,但不是从winform调用时方法结果的选项?

基本上我希望有一些允许来自我的winforms的干净数据调用的东西,而不会使用反射(比如当我返回匿名类型的基元)时使用隐藏的匿名类型,但也不希望仅为了生成类型使用我的IQueryable<T>方法。

3 个答案:

答案 0 :(得分:2)

1)创建一个描述结果的特定类。

2)见1

答案 1 :(得分:2)

在c#中,匿名类型最好用于投影它们的同一方法的范围。正如你所看到的那样,你不能在定义方法之外使用。因此,您无法从方法中返回匿名类型(并保留其结构,您可以将它们作为对象返回,但这不是好主意),这会使您的方法语法无效

最佳选择是将结果投影到为您的需求指定的类。

public class TableJoinResult
{
   public Table1 Table1 { get; set; }
   public Table2 Table2 { get; set;}
}

您的查询:

 public static IQueryable<TableJoinResult> byRecID(Guid recID, MyContext DBContext)
  {
      return (from i1 in DBContext.Table1
             join j1 in DBContext.Table2 on i1.GroupID equals j1.GroupID
             where i1.RecID.Equals(RecID)
             select new TableJoinResult { Table1= i1, Table2 = j1 }).SingleOrDefault();
  }

有关匿名类型的更多信息https://msdn.microsoft.com/en-us/library/bb397696.aspx

答案 2 :(得分:0)

我想避免创建特定的类或结构。 以下是一种避免创建结构/类的冗长方法。 所以我在我的服务类中做到了这一点: -

 List<KeyValuePair<string,int>> IWorkflowService.GetServiceRetention()
        {
           var serviceRetention =  from y in _context.SERVICES
                     join z in _context.SERVICE_SETTINGS on y.ID equals z.SERVICEID
                     select new { Service= y.SERVICE, Retention=z.RETENTION };//new KeyValuePair<string,int?>( y.SERVICE, z.RETENTION ));
            var list = new List<KeyValuePair<string, int>>();
            foreach (var obj in serviceRetention)
            {
                list.Add(new KeyValuePair<string, int>(obj.Service,Convert.ToInt32(obj.Retention)));
            }
            return list;
        }

我必须在我的控制器类中执行此操作:

List<KeyValuePair<string, int>> c = _service.GetServiceRetention();

            foreach (var obj in c)
            {
                 //The key contains service and value contains Rtention.
                  RecurringJob.AddOrUpdate(DELETE_SERVICE + obj.Key, () =>
                  Delete(obj.Key), //this is my function that does the actual process
               Cron.DayInterval(Convert.ToInt32(obj.Value)));
            }

我不确定这是否是最好的方法,但对我有用。