当前位置:  开发笔记 > 编程语言 > 正文

返回匿名类型结果?

如何解决《返回匿名类型结果?》经验,为你挑选了7个好方法。

使用下面的简单示例,使用Linq to SQL从多个表返回结果的最佳方法是什么?

说我有两张桌子:

Dogs:   Name, Age, BreedId
Breeds: BreedId, BreedName

我想用他们的狗归还所有的狗BreedName.我应该让所有的狗使用这样的东西没有问题:

public IQueryable GetDogs()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
                 join b in db.Breeds on d.BreedId equals b.BreedId
                 select d;
    return result;
}

但如果我想要品种的狗并尝试这个我有问题:

public IQueryable GetDogsWithBreedNames()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
                 join b in db.Breeds on d.BreedId equals b.BreedId
                 select new
                        {
                            Name = d.Name,
                            BreedName = b.BreedName
                        };
    return result;
}

现在我意识到编译器不会让我返回一组匿名类型,因为它期待Dogs,但有没有办法在不创建自定义类型的情况下返回它?或者我是否必须创建自己的类DogsWithBreedNames并在select中指定该类型?还是有另一种更简单的方法吗?



1> teedyay..:

我倾向于采用这种模式:

public class DogWithBreed
{
    public Dog Dog { get; set; }
    public string BreedName  { get; set; }
}

public IQueryable GetDogsWithBreedNames()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
                 join b in db.Breeds on d.BreedId equals b.BreedId
                 select new DogWithBreed()
                        {
                            Dog = d,
                            BreedName = b.BreedName
                        };
    return result;
}

这意味着你有一个额外的类,但它编码快速简单,易于扩展,可重用和类型安全.


DataGrids不允许您将属性指定为"Dog.Name"吗?我现在忘了为什么我讨厌他们从不使用它们......
这实际上没有回答OP的问题,"有没有办法在不必创建自定义类型的情况下返回"?

2> Jon Skeet..:

可以返回匿名类型,但它真的不漂亮.

在这种情况下,我认为创建适当的类型会好得多.如果仅在包含该方法的类型中使用它,则将其设置为嵌套类型.

就个人而言,我希望C#获得"命名匿名类型" - 即与匿名类型相同的行为,但具有名称和属性声明,但就是这样.

编辑:其他人建议返回狗,然后通过属性路径等访问品种名称.这是一个非常合理的方法,但IME导致你以特定方式完成查询的情况,因为你想要的数据使用 - 当您返回时,元信息会丢失IEnumerable- 查询可能期望您使用(比如说)Breed而不是Owner由于某些加载选项等,但如果您忘记并开始使用其他属性,您的应用程序可能会工作,但不如你原先设想的那样有效.当然,我可能会说垃圾,或过度优化等等......


我们可能会看到一些滥用.我们可能还会看到一些更简单的代码,基本上我们只需要一个元组.不是*所有*都需要是具有复杂行为的对象.有时"只是数据"是正确的事情.当然是IMO.
嘿,我不是一个不想要功能的人,因为害怕他们会被滥用的方式,但你能想象如果他们允许命名的匿名类型被传递出去,我们会看到的那种狡猾的代码吗?(发抖)

3> Peter Perháč..:

只是为了增加我的两分钱:-)我最近学会了一种处理匿名对象的方法.它只能在面向.NET 4框架时使用,并且仅在添加对System.Web.dll的引用时才使用,但它非常简单:

...
using System.Web.Routing;
...

class Program
{
    static void Main(string[] args)
    {

        object anonymous = CallMethodThatReturnsObjectOfAnonymousType();
        //WHAT DO I DO WITH THIS?
        //I know! I'll use a RouteValueDictionary from System.Web.dll
        RouteValueDictionary rvd = new RouteValueDictionary(anonymous);
        Console.WriteLine("Hello, my name is {0} and I am a {1}", rvd["Name"], rvd["Occupation"]);
    }

    private static object CallMethodThatReturnsObjectOfAnonymousType()
    {
        return new { Id = 1, Name = "Peter Perhac", Occupation = "Software Developer" };
    }
}

为了能够添加对System.Web.dll的引用,您必须遵循rushonerok的建议:确保您的[项目]目标框架是".NET Framework 4"而不是".NET Framework 4 Client Profile".


ASP.NET Mvc School;)

4> joshperry..:

不,你不能通过一些诡计返回匿名类型.

如果您没有使用C#,那么您将要查找的内容(返回多个没有具体类型的数据)称为元组.

有很多C#元组实现,使用这里显示的实现,你的代码将像这样工作.

public IEnumerable> GetDogsWithBreedNames()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
                 join b in db.Breeds on d.BreedId equals b.BreedId
                 select new Tuple(d, b);

    return result;
}

在呼叫网站上:

void main() {
    IEnumerable> dogs = GetDogsWithBreedNames();
    foreach(Tuple tdog in dogs)
    {
        Console.WriteLine("Dog {0} {1}", tdog.param1.Name, tdog.param2.BreedName);
    }
}


这不起作用.引发*NotSupportedException*:_在LINQ to Entities_中仅支持无参数构造函数和初始值设定项

5> tjscience..:

你可以这样做:

public System.Collections.IEnumerable GetDogsWithBreedNames()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
                 join b in db.Breeds on d.BreedId equals b.BreedId
                 select new
                        {
                            Name = d.Name,
                            BreedName = b.BreedName
                        };
    return result.ToList();
}



6> Hakan KOSE..:

必须首先使用ToList()方法从数据库中获取行,然后选择项作为类.试试这个:

public partial class Dog {
    public string BreedName  { get; set; }}

List GetDogsWithBreedNames(){
    var db = new DogDataContext(ConnectString);
    var result = (from d in db.Dogs
                  join b in db.Breeds on d.BreedId equals b.BreedId
                  select new
                  {
                      Name = d.Name,
                      BreedName = b.BreedName
                  }).ToList()
                    .Select(x=> 
                          new Dog{
                              Name = x.Name,
                              BreedName = x.BreedName,
                          }).ToList();
return result;}

所以,首先ToList()是诀窍.它立即进行查询并从数据库中获取数据.第二个技巧是选择项目并使用对象初始化程序生成包含项目的新对象.

希望这可以帮助.



7> Rosdi Kasim..:

在C#7中,您现在可以使用元组!...,这消除了创建类以返回结果的需要。

这是一个示例代码:

public List<(string Name, string BreedName)> GetDogsWithBreedNames()
{
    var db = new DogDataContext(ConnectString);
    var result = from d in db.Dogs
             join b in db.Breeds on d.BreedId equals b.BreedId
             select new
             {
                Name = d.Name,
                BreedName = b.BreedName
             }.ToList();

    return result.Select(r => (r.Name, r.BreedName)).ToList();
}

您可能需要安装System.ValueTuple nuget软件包。

推荐阅读
手机用户2402852387
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有