دوره ی آموزشی Entity Framework in the Enterprise سایت Pluralsight
301, MovedPermanently
http://pluralsight.com/training/Courses/TableOfContents/efarchitecture icon
این آموزش مربوطه به چند ماه قبل هست ..
این آموزش را به صورت خلاصه دیدم و سورس‌های آن را بررسی کردم. 
نکات خوبی دارد ، به خصوص قسمت آخر آن (  Automated Testing )
به عقیده‌ی من پیاده سازی الگوی Context Per Request  که در سایت جاری آموزش داده شده نسبت به پیاده سازی این دوره‌ی آموزشی روان‌تر است.
 کلاس‌های Repository که در مثال Pluralsight نوشته شدند بعضا نوع بازگشتی IQueryable دارند که در نهایت به یک leaky abstraction رسیده است.
پیاده سازی الگوی Unit Of Work دوره‌ی Pluralsight پیچیده گی هایی دارد که من علت آن را متوجه نشدم.
دوره ی آموزشی Entity Framework in the Enterprise سایت Pluralsight
  • #
    ‫۱۰ سال و ۱۱ ماه قبل، یکشنبه ۵ آبان ۱۳۹۲، ساعت ۲۲:۱۷
    کلاس‌های Repository که در مثال Pluralsight نوشته شدند بعضا نوع بازگشتی IQueryable دارند که در نهایت به  یک leaky abstraction رسیده است. 
    منظور شما این است که نباید خروجی توابع درون Repository از نوع IQueryable باشد؟
    مثلا من توی پروژم BranchRepository را به صورت زیر پیاده کردم. آیا این روش ایراد دارد؟ 
     public interface IBranchRepository
        {
            IQueryable<Branch> GetAll();
            IQueryable<Branch> GetAllWithAll();
            void Update(Branch branch);
            void Create(Branch branch);
            void Delete(Branch branch);
            IQueryable<Branch> GetAllwithCorporate();
        }
    
        public class BranchRepository : BaseRepository, IBranchRepository
        {
            public BranchRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
            {
            }
    
            public IQueryable<Branch> GetAll()
            {
                return GetDbSet<Branch>();
            }
    
            public IQueryable<Branch> GetAllWithAll()
            {
                return GetDbSet<Branch>().Include(x=>x.Corporate).Include(x=>x.City).Include(x=>x.Province);
            }
    
    
            public IQueryable<Branch> GetAllwithCorporate()
            {
                return GetDbSet<Branch>().Include(x=>x.Corporate);
            }
    
            public void Update(Branch branch)
            {
                SetCurrentValues(GetDbSet<Branch>().FirstOrDefault(x => x.BranchID == branch.BranchID),branch);
                unitOfWork.SaveChanges();
            }
            public void Create(Branch branch)
            {
                GetDbSet<Branch>().Add(branch);
                unitOfWork.SaveChanges();
            }
    
            public void Delete(Branch branch)
            {
                GetDbSet<Branch>().Remove(branch);
                unitOfWork.SaveChanges();
            }
        }

      • #
        ‫۱۰ سال و ۱۱ ماه قبل، دوشنبه ۶ آبان ۱۳۹۲، ساعت ۱۶:۱۴
        فرض کنید لایه سرویس هم به این شکل باشد :
        public IQueryable<Branch> GetAlls()
        {
                return _branchRepository.GetAllwithCorporate();
        }
        
         public IQueryable<Branch> GetAllWithAll()
        {
                 var CorporateID = _serverApplicationSettingRepository.GetAll().FirstOrDefault().CorporateID;
                 return _branchRepository.GetAllWithAll().Where(x => x.CorporateID == CorporateID);
        }

        مساله ای که هست اینه که ما نمیخواهیم برای بیرون کشیدن یک رکورد در Controller، در لایه سرویس یا مخزن کل رکوردها رو بیرون بکشیم.
        اگر قرار باشد در لایه سرویس از نوع IList یا IEnumberable برای خروجی استفاده کنیم، یعنی در واقع کل رکوردها رو واکشی کردیم که شاید فقط در Controller نیاز به یک رکورد باشد. یعنی بستن کوئری در لایه سرویس یا مخزن، ممکنه باعث اجبار در واکشی همه رکوردها در لایه‌های پایین، حتی برای حالتی که ما فقط به یک رکورد نیاز داریم بشه.
        پس راه حل چیه؟
        • #
          ‫۱۰ سال و ۱۱ ماه قبل، دوشنبه ۶ آبان ۱۳۹۲، ساعت ۱۶:۲۰
          public IList<User> FindUsersContainName(string name, int count = 20)

          از متدهای ریزتر استفاده کنید در لایه سرویس. GetAll فقط یکی از متدها است. مثلا متد تعریف کنید مثل امضای فوق که حد و مرز مشخص و کوچکی دارد مخصوص یک قسمت خاص از کار برنامه.

        • #
          ‫۱۰ سال و ۱۱ ماه قبل، دوشنبه ۶ آبان ۱۳۹۲، ساعت ۱۷:۳۰
          شما برای لایه سرویس محدودیتی ندارید.هر متدی که نیاز داری پیاده سازی کن.مثلا:
              public class CityService : ICityService
              {
                  private readonly IUnitOfWork _uow;
                  private readonly IDbSet<City> _city;
          
                  public CityService(IUnitOfWork uow)
                  {
                      _uow = uow;
                      _city = _uow.Set<City>();
                  }
          
                  public int AddCity(City city)
                  {
                      ...
                  }
          
                  public int CitiesCount()
                  {
                      ...
                  }
          
                  public City SearchByCityName(string cityName)
                  {
                      ....
                  }
          
                  public void EditCity(City city)
                  {
                    ...
                  }
          
          
                  public int RemoveCity(City city)
                  {
                      ...
                  }
          
          
                  public City GetOneCity(int cityId)
                  {
                      return _city.Include(a => a.Province).Include(a => a.Province.Country).FirstOrDefault(a => a.CityId == cityId);
                  }
          
                  public IList<City> AllCities()
                  {
                      return _city.Include(a => a.Province).Include(a => a.Province.Country).ToList();
                  }
          
                  public IList<City> SearchByProvinceId(int provinceId)
                  {
                      return _city.Where(c => c.ProvinceId == provinceId).ToList();
                  }
          
                  public IList<City> GetCities(int startIndex, int pageSize, string sortexpression)
                  {
                      if (sortexpression == string.Empty)
                      {
                          sortexpression = "CityId ASC";
                      }
          
                      string sortColumnName = sortexpression.Split(' ')[0];
                      string sortDirection = sortexpression.Split(' ')[1];
                      var citiesQuery = _city.Include(a => a.Province).Include(a => a.Province.Country).AsQueryable();
                      switch (sortColumnName)
                      {
                          case "CityId":
                              citiesQuery = ((sortDirection.ToLower() == "asc") ? citiesQuery.OrderBy(a => a.CityId) : citiesQuery.OrderByDescending(a => a.CityId));
                              break;
                          case "CityName":
                              citiesQuery = ((sortDirection.ToLower() == "asc") ? citiesQuery.OrderBy(a => a.CityName) : citiesQuery.OrderByDescending(a => a.CityName));
                              break;
                          case "TelCode":
                              citiesQuery = ((sortDirection.ToLower() == "asc") ? citiesQuery.OrderBy(a => a.TelCode) : citiesQuery.OrderByDescending(a => a.TelCode));
                              break;
          ...
                      }
                      return citiesQuery.Skip(startIndex).Take(pageSize).ToList();
                  }
          
          ....و هر متد دیگری که نیاز دارید
              }
          هر متد دیگری که نیاز داری میتونی پیاده سازی کنی.
          برای نمونه پروژه IRIS را بررسی کنید.