C# 不确定此代码,有代码气味!

C# 不确定此代码,有代码气味!,c#,asp.net,linq,C#,Asp.net,Linq,这个密码让我很烦 我创建了一个单独的对象EventDistance,但我认为可能不需要它,只是我不知道如何以不同的方式编写代码。距离是我为事件添加到分部类的一个属性。基本上我想返回所有事件并按距离排序 我认为额外的一轮foreach可能是不必要的 public IQueryable<Event> FindByLocation(float latitude, float longitude) { var eventsList = from ev

这个密码让我很烦

我创建了一个单独的对象EventDistance,但我认为可能不需要它,只是我不知道如何以不同的方式编写代码。距离是我为事件添加到分部类的一个属性。基本上我想返回所有事件并按距离排序

我认为额外的一轮foreach可能是不必要的

public IQueryable<Event> FindByLocation(float latitude, float longitude)
        {

            var eventsList = from ev in GetAllEvents()
                             join i in db.NearestEvents(latitude, longitude)
                             on ev.ID equals i.ID
                             select new EventDistance() { TheEvent = ev, Distance = i.Distance };


            foreach (var item in eventsList)
            {
                item.TheEvent.Distance = item.Distance;  
            }
            return eventsList.OrderBy(e => e.Distance).Select(e => e.TheEvent);
        } 
public IQueryable FindByLocation(浮动纬度、浮动经度)
{
var eventsList=来自GetAllEvents()中的ev
在db.NearestEvents(纬度、经度)中加入i
关于ev.ID等于i.ID
选择neweventdistance(){TheEvent=ev,Distance=i.Distance};
foreach(事件列表中的变量项)
{
item.TheEvent.Distance=item.Distance;
}
returneventslist.OrderBy(e=>e.Distance);
} 

在我看来,您不应该需要
EventDistance
类。只需省略它,并通过在LINQ表达式中不指定任何类型来使用匿名类型:

public IQueryable<Event> FindByLocation(float latitude, float longitude)
    {

        var eventsList = from ev in GetAllEvents()
                         join i in db.NearestEvents(latitude, longitude)
                         on ev.ID equals i.ID
                         select new { TheEvent = ev, Distance = i.Distance };


        foreach (var item in eventsList)
        {
            item.TheEvent.Distance = item.Distance;  
        }
        return eventsList.OrderBy(e => e.Distance).Select(e => e.TheEvent);
    } 
public IQueryable FindByLocation(浮动纬度、浮动经度)
{
var eventsList=来自GetAllEvents()中的ev
在db.NearestEvents(纬度、经度)中加入i
关于ev.ID等于i.ID
选择新的{TheEvent=ev,Distance=i.Distance};
foreach(事件列表中的变量项)
{
item.TheEvent.Distance=item.Distance;
}
returneventslist.OrderBy(e=>e.Distance);
} 

我对LINQ语法一无所知,但是应该可以在第一个
选择中填充距离值。差不多

var eventsList = from ev in GetAllEvents()
                 join i in db.NearestEvents(latitude, longitude)
                 on ev.ID equals i.ID
                 orderby i.Distance
                 select (ev => { ev.Distance = i.Distance; return ev; });
??或者,正确书写:-)


注意:正如下面的qstarin注释所述,只有当我们在此时处理对象,而不是被评估为SQL的ORM对象时,这才可能实现。也就是说,你可能仍然可以

  • 在初始获取中执行orderby
  • 强制对象进入内存(我忘记了最好的方法)
  • 使用单个选择将对象组合到事件对象中(如上所述),而不是循环

  • 如果要将其保留为IQueryable,可以执行以下操作:

            public IQueryable<Event> FindByLocation(float latitude, float longitude)
            {
    
                return from ev in GetAllEvents()
                       join i in db.NearestEvents(latitude, longitude)
                       on ev.ID equals i.ID
                       order by i.Distance
                       select ev;
            }
    
    public IQueryable FindByLocation(浮动纬度、浮动经度)
    {
    从GetAllEvents()中的ev返回
    在db.NearestEvents(纬度、经度)中加入i
    关于ev.ID等于i.ID
    按距离排序
    选择电动汽车;
    }
    
    只要GetAllEvents()方法也返回IQueryable,就是这样

    编辑:我现在已经实际试用了下面Rup的建议,您应该能够返回IQueryable,而无需在这个方法中调用db调用。像这样:

            public IQueryable<EventDistance> FindByLocation(float latitude, float longitude)
            {
                    return from ev in GetAllEvents()
                       join i in db.NearestEvents(latitude, longitude)
                       on ev.ID equals i.ID
                       orderby i.Distance
                       select new EventDistance
                       {
                           Event = ev,
                           Distance = i.Distance
                       };
           }
    
    public IQueryable FindByLocation(浮动纬度、浮动经度)
    {
    从GetAllEvents()中的ev返回
    在db.NearestEvents(纬度、经度)中加入i
    关于ev.ID等于i.ID
    orderby i.距离
    选择新事件距离
    {
    事件=ev,
    距离=i.距离
    };
    }
    

    EventDistance类不需要映射。

    您可以这样做吗

    public IQueryable<Event> FindByLocation(float latitude, float longitude)
        {
    
            var eventsList = from ev in GetAllEvents()
                             join i in db.NearestEvents(latitude, longitude)
                             on ev.ID equals i.ID
                             select new Event { ID = ev.ID, Distance = i.Distance };
    
    
            return eventsList.OrderBy(e => e.Distance).AsQueryable();
        } 
    
    public IQueryable FindByLocation(浮动纬度、浮动经度)
    {
    var eventsList=来自GetAllEvents()中的ev
    在db.NearestEvents(纬度、经度)中加入i
    关于ev.ID等于i.ID
    选择新事件{ID=ev.ID,Distance=i.Distance};
    返回eventsList.OrderBy(e=>e.Distance.AsQueryable();
    } 
    
    如果LINQ表达式由试图将其转换为SQL的提供程序处理,则这可能不起作用。如果是针对内存中的对象发生的,则应该可以使用.re#2,在选择/投影(或任何需要的地方)之前插入.ToList()将强制计算IQueryable并加载DB对象。@qstarin是的,我通常就是这样做的,但我有一半希望有更好的技巧。总而言之,我现在想我们应该说服他不要扔掉temp对象,这样我们就不会在这个函数中读取内存了。哦,好吧。我经常思考LINQ提供者如何能够更聪明地处理转换成SQL的内容,并能够将这些操作与需要对对象执行的操作分离开来。我不知道有任何LINQ提供程序可以这样做,但最好不要到处散布.ToList()。但是,您已经丢失了I.Distance属性-在他的示例中,他将其存储到事件对象中以返回。我开始认为最好的答案是修改您的方法以
    选择新的EventDistance()){TheEvent=ev,Distance=i.Distance}
    并返回一个
    IQueryable
    -这行得通吗?我怀疑它行不通,因为它不是数据层知道的对象-尽管它有映射到的方法。我现在很困惑。我实际上也在想同样的事情,但我已经很久没有使用LINQ进行数据访问了,所以我真的这么做了不知道它是否会:)…但我刚刚启动了VS来试用。我会回来的。它工作正常!它返回一个IQueryable而不接触数据库。
    public IQueryable<Event> FindByLocation(float latitude, float longitude)
        {
    
            var eventsList = from ev in GetAllEvents()
                             join i in db.NearestEvents(latitude, longitude)
                             on ev.ID equals i.ID
                             select new Event { ID = ev.ID, Distance = i.Distance };
    
    
            return eventsList.OrderBy(e => e.Distance).AsQueryable();
        }