簡體   English   中英

如何在使用空間類型和自動化時優化實體框架查詢?

[英]How to optimize Entity Framework query when using spatial types and automapper?

我正在建設的不是非常獨特的東西。 簡而言之,我正在創建一個使用ASP.NET MVC 4(Web Api)和Entity Framework 5(帶有Spatial支持)在Azure中運行的小型FourSquare服務。 所以我使用的是SQL Azure,而不是像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;
}

我想我需要澄清一些事情。 locationEntityRepository.GetAll看起來像這樣。

public IQueryable<LocationEntity> GetAll
{
    get { return _context.Locations; }
}

public IQueryable<LocationEntity> GetAllIncluding(params Expression<Func<LocationEntity, object>>[] includeProperties)
{
    IQueryable<LocationEntity> query = _context.Locations;
    foreach (var includeProperty in includeProperties) {
        query = query.Include(includeProperty);
    }

    // var tmp = query.ToList();

    return query;
}

現在代碼真的聞起來很時髦。 理想情況下,我希望能夠使用GetAllIncluding(c => c.Checkins)而不是GetAll方法,並且能夠使用AutoMapper在LINQ投影中進行映射。

我知道在使用子查詢時,Include + LINQ / EF按設計返回null。 在LINQ / EF查詢中使用automapper應該使用Project().To<> ,但在使用.ForMember.ForMember

所以挑戰在於使代碼更高效(當需要更改我的JSON結構時,更少的SQL並且易於維護。請記住,我們試圖在這里擊敗node.js / MongoDB;)我應該打擾,還是留下它是什么?

我使用Repository模式做了類似的事情。

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

    public IEnumerable<T> FindBy(Expression<Func<T, bool>> predicate)
    {
        return _context.Set<T>().Where(predicate);
    }

.Set方法的位置

    public IDbSet<TEntity> Set<TEntity>() where TEntity : class
    {
        return base.Set<TEntity>();
    }

這允許您從數據庫中獲取類型的所有內容,或者只獲取滿足特定條件的所有類型。

這將為您留下一個對象列表,或者如果您使用FirstOrDefault()一個對象,您可以根據需要進行映射。

三件事。

  1. 包括System.Data.Entity命名空間。 include方法實際上是該命名空間引入的擴展。 它甚至更適合使用EF 4.1及更高版本中提供的Lambda重載,因此,您必須在任何想要調用它的地方添加命名空間。
  2. 刪除第一個查詢末尾的.ToList(),因為它立即執行了違反包含目的的查詢。

     using System.Data.Entity public IQueryable<LocationEntity> GetAll { get { return _context.Locations; } } 

這樣,您可以在子查詢上使用Include

為什么不用這個:

Context context=new Context();
Public List<LocationEntity> GetAll()
{
    return context.LocationEntities.Include("includeProperty").ToList();
}

而Context是這樣的:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM