繁体   English   中英

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

[英]Entity Framework returning IQueryable of join of two tables

我想使用Entity Framework从2个表中返回数据,并从2个表中选择列,起初我对简单的东西不太满意,例如返回int和字符串(例如, select new { id = t1.ID, other = t2.OtherData } ,因为在目的地(目标位置是我的winform)上强制转换匿名类型非常麻烦,所以我想到了只返回两个表行的想法...

所以像这样:

  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();
  }

除了方法的返回类型不正确外,这一切都很好。 我尝试了几种组合。 不幸的是,当我从winform调用“ byRecID”时,“ SingleOrDefault”不可用,但是在“ byRecID”方法中可用,因此我不能只返回IQueryable ,而需要将其键入IQueryable<SOMETHING IN HERE> (因为SingleOrDefault不是IQueryable的扩展,只有IQueryable<T> )。

我的问题...“这里有东西”是否有一种语法,可以让我指定其两个表行的连接?

而且我想知道...当从Winform调用SingleOrDefault时,为什么在方法中包含选项而不是方法结果的选项?

基本上,我希望能够允许从winforms进行干净的数据调用,而不必转换为可怕的匿名类型,然后使用反射(例如当我返回匿名类型的基元时),但是我也不想产生一个供我使用的Type byRecID方法。

在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

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

2)查看1

我想避免创建特定的类或结构。 下面是避免创建结构/类的冗长方法。 所以我在我的服务班上做了这个:

 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)));
            }

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

暂无
暂无

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

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