Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在使用空间类型和自动映射时优化实体框架查询?_C#_Linq_Entity Framework 5_Spatial_Automapper 2 - Fatal编程技术网

C# 如何在使用空间类型和自动映射时优化实体框架查询?

C# 如何在使用空间类型和自动映射时优化实体框架查询?,c#,linq,entity-framework-5,spatial,automapper-2,C#,Linq,Entity Framework 5,Spatial,Automapper 2,我正在建设的东西不是很独特。简而言之,我正在使用ASP.NETMVC4(WebAPI)和EntityFramework5(具有空间支持)在Azure中创建一个类似FourSquare的小服务。所以我使用的是SQLAzure,而不是像MongoDB或CouchDB这样的NoSQL数据库。部分原因是我对.NET更为熟悉,部分原因是为了了解开发经验(重构、部署、测试),部分原因是为了了解它将如何与node.js/MongoDB相抗衡 现在让我们看一些代码 /// <summary> ///

我正在建设的东西不是很独特。简而言之,我正在使用ASP.NETMVC4(WebAPI)和EntityFramework5(具有空间支持)在Azure中创建一个类似FourSquare的小服务。所以我使用的是SQLAzure,而不是像MongoDB或CouchDB这样的NoSQL数据库。部分原因是我对.NET更为熟悉,部分原因是为了了解开发经验(重构、部署、测试),部分原因是为了了解它将如何与node.js/MongoDB相抗衡

现在让我们看一些代码

/// <summary>
/// Return the nearest locations relative from the given longitude/latitude
/// </summary>
/// <param name="longitude">Longitude</param>
/// <param name="latitude">Latitude</param>
/// <param name="maxresults">Optional maximum results, default is 2</param>
/// <param name="radius">Optional maximum radius in kilometres, default is 50 km</param>
/// <returns></returns>
public JsonEnvelope Get(string longitude, string latitude, int maxresults = 2, int radius = 50)
{
    var pointTxt = string.Format("POINT({0} {1})", longitude, latitude);
    var locations = (from s in locationEntityRepository.GetAll
                     orderby s.Coordinates.Distance(DbGeography.FromText(pointTxt))
                     where s.Coordinates.Distance(DbGeography.FromText(pointTxt)) / 1000  <= radius
                     select new Location
                     {
                         Id = s.Id,
                         Name = s.Name,
                         LocationType = s.LocationType,
                         Address = s.Address,
                         Longitude = s.Coordinates.Longitude.Value,
                         Latitude = s.Coordinates.Latitude.Value,
                         Distance = (s.Coordinates.Distance(DbGeography.FromText(pointTxt)).Value) / 1000
                      })
                    .Take(maxresults).ToList();

    // Bad bad bad. But EF/Linq doesn't let us do Includes when using subqueries... Go figure
    foreach (var location in locations)
    {
        location.Checkins = AutoMapper.
                            Mapper.
                            Map<List <Checkin>, List<LocationCheckinsJsonViewModel>>
                                (checkinRepository.GetCheckinsForLocation(location.Id).ToList());
    }

    // AutoMapper.Mapper.Map<Checkin, CheckinViewModel>(dbCheckin);
    var jsonBuilder = new JsonResponseBuilder();
    jsonBuilder.AddObject2Response("locations", locations);

    return jsonBuilder.JsonEnvelope;
}
现在代码闻起来真的很怪。理想情况下,我希望能够使用
GetAllIncluding(c=>c.Checkins)
而不是
GetAll
方法,并且能够使用
AutoMapper
在LINQ投影内进行映射

我知道使用子查询时,Include+LINQ/EF是按设计返回null的。在LINQ/EF查询中使用automapper应该通过
Project().To
完成,但在使用
.ForMember
时,这不起作用


因此,挑战在于提高代码的效率(减少SQL并在需要更改JSON结构时易于维护。请记住,我们在这里试图击败node.js/MongoDB;)我应该费心还是保持原样?

我使用存储库模式做了类似的事情

    public IEnumerable<T> FindAll()
    {
        return _context.Set<T>().ToList();
    }

    public IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
    {
        return _context.Set<T>().Where(predicate);
    }
public IEnumerable FindAll()
{
返回_context.Set().ToList();
}
公共IEnumerable FindBy(表达式谓词)
{
返回_context.Set().Where(谓词);
}
其中.Set方法是

    public IDbSet<TEntity> Set<TEntity>() where TEntity : class
    {
        return base.Set<TEntity>();
    }
public IDbSet(),其中tenty:class
{
返回base.Set();
}
这允许您从数据库中获取某个类型的所有内容,或者仅获取满足特定条件的所有类型

这就留下了一个对象列表,或者如果使用FirstOrDefault(),则可以根据需要映射单个对象。

三件事

  • 包括
    System.Data.Entity
    命名空间。
    include
    方法实际上是该名称空间引入的扩展。更可取的做法是使用在EF4.1及更高版本中可用的Lambda重载,因此,您必须在想要调用它的任何地方添加名称空间
  • 删除第一个查询末尾的.ToList(),因为它会立即执行违反包含目的的查询

    using System.Data.Entity
    public IQueryable<LocationEntity> GetAll
    {
        get
        {
            return _context.Locations;
        }
    }
    
    使用System.Data.Entity
    公共iqueryablegetall
    {
    得到
    {
    返回上下文位置;
    }
    }
    
  • 这样,您就可以在子查询中使用Include了

    为什么不使用这个:

    Context context=new Context();
    Public List<LocationEntity> GetAll()
    {
        return context.LocationEntities.Include("includeProperty").ToList();
    }
    
    Context Context=newcontext();
    公共列表GetAll()
    {
    返回context.LocationEntities.Include(“includeProperty”).ToList();
    }
    
    背景是:

    public class Context: DbContext
        {
            public Context()
            {
                base.Configuration.LazyLoadingEnabled = false;
                base.Configuration.ProxyCreationEnabled = false;
                base.Configuration.ValidateOnSaveEnabled = false;
            }
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            }
            public DbSet<LocationEntity> LocationEntities{ get; set; }
        }
    
    公共类上下文:DbContext
    {
    公共上下文()
    {
    base.Configuration.LazyLoadingEnabled=false;
    base.Configuration.ProxyCreationEnabled=false;
    base.Configuration.ValidateOnSaveEnabled=false;
    }
    模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
    {
    基于模型创建(modelBuilder);
    modelBuilder.Conventions.Remove();
    }
    公共数据库集位置实体{get;set;}
    }
    
    我不知道问题出在哪里。如果在select语句中的
    位置EntityRepository之后添加
    。Include(“Checkins”)
    。GetAll
    EF不允许吗?(其中“Checkins”是实体上导航属性的名称)我必须承认我更喜欢基于方法的Linq语句,并且没有/不能测试上面的代码。但乍一看,这似乎是一个语法问题。但即使没有,您也可以编写请求的“GetAllIncluding()”方法,我认为这不是正确的方法。如果我误解了,请编辑您的问题,将两个实体模型的代码包括在内。#1可以,但不能解决根本问题-它只是语法上的问题#2,命名空间问题将在编译时出现,与此无关,因为上面的示例已经编译#3、ToList()并不违背包含的目的。它将执行包含子实体或集合的查询。您是对的。更改为DbSet甚至会将您的实现与实体框架联系起来,而实体框架并非在所有情况下都是理想的。
    public class Context: DbContext
        {
            public Context()
            {
                base.Configuration.LazyLoadingEnabled = false;
                base.Configuration.ProxyCreationEnabled = false;
                base.Configuration.ValidateOnSaveEnabled = false;
            }
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
            }
            public DbSet<LocationEntity> LocationEntities{ get; set; }
        }