2013-03-08 68 views
1

我试图返回一组使用子字符串修剪的独特结果,但当我调用“Select”时,它会将其转换为匿名类型。我似乎无法得到这个维护类型“列表”。我只需要返回Select方法中指定的字段。如何在C#中使用LINQ .Select时保持类型?

public List<Facility> GetFacilities() { 
    var facilities = new List<Facility>(); 
    facilities = _facilityRepository.GetAll().ToList(); 
    var facReturnList = 
     facilities.Where(x => x.Fac_Name = "Something") 
        .OrderBy(x => x.Fac_Name).ToList(); 

    var facReturnList2 = 
     facReturnList.Select(x => 
      new { ID = x.Fac_Name.Substring(0, 6), 
        Fac_Name = x.Fac_Name.Substring(0, 3) }) 
      .Distinct().ToList(); 
    return facReturnList2; 
} 

我试图new后加入List<Facility>,但它说,这些属性(IDFac_Name)的设施没有定义。

+0

您可能会更好地使用Facility的模型而不是返回实体本身。此外,您通常可以通过在查询之间不使用'.ToList()'来修剪查询。前两个linq查询可能不需要对'ToList'的调用,除非您使用的独特不可转换为sql。 (我们是在谈论一个datacontext顺便说一句吗?) – Silvermind 2013-03-08 18:07:14

+0

@Silvermind,认为你在这两个帐户上都是正确的,但我对这种技术是新的,因此我不能肯定地说这是一个“datacontext” – JamesRLamar 2013-03-08 18:15:24

回答

3

您是否想用结果初始化新的Facility实例?

var facReturnList2 = facReturnList.Select(x => new Facility { ID = // ... 
               ^concrete type initializer 

响应编辑:里面的Select运营商,你需要指定元素要初始化,不是他们的类型。您之前的代码似乎表明Fac_NameFacility中定义的,但它显然不会在List<Facility>中定义。

+0

这就是我所缺少的。我只需要把它作为一个设施而不是一个列表。谢谢! – JamesRLamar 2013-03-08 18:04:14

+3

你需要*构建它作为一个设施,而不是投它 – fguchelaar 2013-03-08 18:05:38

+0

@fguchelaar,我觉得这个术语是不正确的。我一定会考虑的。 – JamesRLamar 2013-03-08 18:14:01

2

您正在创建一个匿名类型,因为您正在创建它。

.Select(x => new { 

如果你不想这样做,不要这样做。

如果现有类型已经具有您需要的名称和确切的属性,请使用它。如果没有你需要的类型,创建一个。然后您可以返回该类型的适当列表或枚举类型。

.Select(x => new YourDefinedType { 
1

下面的代码是指示LINQ返回一个匿名类型:

.Select(x => new { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) } 

你需要创建一个类你的结果

public class Result{ 
    public string ID { get;set; } 
    public string Fac_Name { get; set; } 
} 

//Then do 

.Select(x => new Result { ID = x.Fac_Name.Substring(0, 6), Fac_Name = x.Fac_Name.Substring(0, 3) } 

这将确保你只返回你需要

信息
2

这听起来像你真正想要的是一个DistinctBy方法。你想要指定一些方法来指示一个对象是不同的,但你不希望结果是该选择的集合,你希望最终的结果成为起始对象。 LINQ没有DistinctBy内置的,但实现一个是很容易的:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, 
    Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer = null) 
{ 
    comparer = comparer ?? EqualityComparer<TKey>.Default; 
    HashSet<TKey> knownKeys = new HashSet<TKey>(comparer); 
    foreach (TSource element in source) 
    { 
     if (knownKeys.Add(keySelector(element))) 
     { 
      yield return element; 
     } 
    } 
} 

使用你的代码现在可以变为:

public List<Facility> GetFacilities() 
{ 
    return _facilityRepository.GetAll() 
     .Where(x => x.Fac_Name == "Something") 
     .DistinctBy(x => new 
     { 
      ID = x.Fac_Name.Substring(0, 6), 
      Fac_Name = x.Fac_Name.Substring(0, 3) 
     }) 
     .OrderBy(x => x.Fac_Name) 
     .ToList(); 
} 

在你有一个IQueryable在内存而不是一个事件数据集,您可以使用GroupBy来获得相同的行为。在使用GroupBy的Linq-to-objects中效率会低很多,但对于查询提供者而言,它不会像数据库能够优化这一点。

public List<Facility> GetFacilities() 
{ 
    return _facilityRepository.GetAll() 
     .Where(x => x.Fac_Name == "Something") 
     .OrderBy(x => x.Fac_Name) 
     .GroupBy(x => new 
     { 
      ID = x.Fac_Name.Substring(0, 6), 
      Fac_Name = x.Fac_Name.Substring(0, 3) 
     }) 
     .Select(group => group.First()) 
     .ToList(); 
} 
+0

我仍然没有得到明显的结果,并且使用您的代码“DistinctBy”不是公认的扩展方法。我将在这里创建关于这个问题的另一个问题,http://stackoverflow.com/questions/15301068/how-to-get-a-distinct-result-using-linq-and-c-sharp-using-method-syntax。我认为你的答案和这一个可能是在正确的轨道,http://stackoverflow.com/questions/8853390/select-distinct-from-datatable-using-linq-and-c-sharp – JamesRLamar 2013-03-08 18:44:00

+0

@JamesRLamar我提供了定义在这篇文章中的扩展方法。正如我所说,它不在LINQ本身。 – Servy 2013-03-08 18:48:23

+0

我得到了你。我像你所建议的那样为它添加了静态类。在后台我有一些其他的东西来获取存储库,所以我猜这就是冲突可能发生的地方。我非常感谢你的帮助。 – JamesRLamar 2013-03-08 20:18:43

相关问题