Messii
Member
tôi thấy ông thread nói cũng có lý sài orm rồi thì dẹp cai repository còn tôi thì chỉ sài DAL tự viết nên sài thêm thằng repository, nói chung cũng còn tuỳ sở thích nữa
via theNEXTvoz for iPhone
via theNEXTvoz for iPhone
Therefore, use a Repository, the purpose of which is to encapsulate all the logic needed to obtain object references. The domain objects won’t have to deal with the infrastructure to get the needed references to other objects of the domain. They will just get them from the Repository and the model is regaining its clarity and focus. The Repository may store references to some of the objects. When an object is created, it may be saved in the Repository, and retrieved from there to be used later. If the client requested an object from the Repository, and the Repository does not have it, it may get it from the storage. Either way, the Repository acts as a storage place for globally accessible objects.
Tôi nghĩ là các anh nên thống nhất lại cái định nghĩa về Repository đi. Cái GenericRepository là sai về mặt định nghĩa rồi, Output của nó là IQueryable cũng là sai định nghĩa rồi. Bàn luận trên 1 cái sai thì bàn đến bao giờ .
DDD Quickly
nếu dùng ORM thay thế cho repository, tức là chúng ta sẽ inject Dbcontext vào các service chúng ta cần và gọi _context.Account.Find, hay là _context.Account.Where .. Include ... hoặc cũng có thể là
_context.Account.Where...Select(x=>x.GetFromAnotherSource()).toList ...
-----
nếu dùng repository chúng ta sẽ chỉ có:
getbyId
getAccountWith ...
----
và như thế chúng ta đã tránh việc lặp code ^^ cũng như một loại lợi ích khác
----
Một số entity chúng ta có thể dùng repository pattern, nhưng một số chỉ cần generic repository. vì nó hầu hết chỉ là CRUD
Tôi nghĩ là các anh nên thống nhất lại cái định nghĩa về Repository đi. Cái GenericRepository là sai về mặt định nghĩa rồi, Output của nó là IQueryable cũng là sai định nghĩa rồi. Bàn luận trên 1 cái sai thì bàn đến bao giờ .
DDD Quickly
Cái này khá đơn giản.Còn 1 cái nữa liên quan đến DI, và việc giải resolve nó (scoped, transient, singleton) cũng chưa thấy ông nào nhắc đến mối quan hệ của nó trong repo + uow
Anh ếch xanh chê là microsoft viết cái repository pattern sai rồi
https://docs.microsoft.com/en-us/as...f-work-patterns-in-an-asp-net-mvc-application
Nhưng theo tôi thì nó viết không sai, mà nó viết chung chung quá. Repository Pattern của Microsoft viết thì dữ liệu nó đã được chuyển qua IEnumerable (In-memory) mà không phải IQueryable (build sql). Tức là về tính chất thì nó không sai nhưng nó viết 1 case quá cơ bản nên nhiều người nhiều sai.
private GenericRepository<Department> departmentRepository;
private GenericRepository<Course> courseRepository;
.........
courseRepository.ListAvaiableCourseDepartments(); // bên trong sẽ join Course và Department
Trên Google có thể tìm được rất nhiều bài viết về GenericRepository mà mỗi function sẽ trả ra IQueryable (cái này thì cơ bản là sai về định nghĩa của Repository Pattern) và cái này là thừa (tôi đồng ý với quan điểm thừa anh ếch xanh)
from departmentRepository d
join courseRepository c on c.DepartmentId = d.Id....
Cái này khá đơn giản.
Scoped = mỗi thread thì 1 class sẽ chỉ sinh ra 1 object tương ứng, do đó việc inject giữa nhiều service khác nhau thực chất vẫn là 1 object, do đó có thể thực hiện transaction của UOW được.
Transient = mỗi class sẽ tự tạo 1 object tương ứng với lần inject đó => không thực hiện được UOW transaction vì DataContext nó khác nhau.
Singleton = tạo 1 object xuyên suốt life time của ứng dụng => xung đột dữ liệu của DataContext khi có nhiều thread thực hiện vì EF yêu cầu thread safe.
=> Do đó cách dùng đúng của UOW là phải dùng Scoped thôi.
Về Database connection pool thì mặc định từ bản 3.1 trở xuống thì với connection string không chỉ định connection pool thì set là 100 connection. Còn với bản EF 5 trở lên thì đã bỏ giới hạn này đi. Do đó với các ứng dụng nhiều luồng truy cập thì phải nâng maximum connection pool lên 1000 hoặc hơn, tùy vào stress testing thôi. Còn cái chuyện connection pool tức là nó dùng connection xong thì nó trả về pool cho thread khác sử dụng thôi.
Anh ếch xanh chê là microsoft viết cái repository pattern sai rồi
https://docs.microsoft.com/en-us/as...f-work-patterns-in-an-asp-net-mvc-application
Nhưng theo tôi thì nó viết không sai, mà nó viết chung chung quá. Repository Pattern của Microsoft viết thì dữ liệu nó đã được chuyển qua IEnumerable (In-memory) mà không phải IQueryable (build sql). Tức là về tính chất thì nó không sai nhưng nó viết 1 case quá cơ bản nên nhiều người nhiều sai.
Trên Google có thể tìm được rất nhiều bài viết về GenericRepository mà mỗi function sẽ trả ra IQueryable (cái này thì cơ bản là sai về định nghĩa của Repository Pattern) và cái này là thừa (tôi đồng ý với quan điểm thừa anh ếch xanh)
Cái này khá đơn giản.
Scoped = mỗi thread thì 1 class sẽ chỉ sinh ra 1 object tương ứng, do đó việc inject giữa nhiều service khác nhau thực chất vẫn là 1 object, do đó có thể thực hiện transaction của UOW được.
Transient = mỗi class sẽ tự tạo 1 object tương ứng với lần inject đó => không thực hiện được UOW transaction vì DataContext nó khác nhau.
Singleton = tạo 1 object xuyên suốt life time của ứng dụng => xung đột dữ liệu của DataContext khi có nhiều thread thực hiện vì EF yêu cầu thread safe.
=> Do đó cách dùng đúng của UOW là phải dùng Scoped thôi.
Về Database connection pool thì mặc định từ bản 3.1 trở xuống thì với connection string không chỉ định connection pool thì set là 100 connection. Còn với bản EF 5 trở lên thì đã bỏ giới hạn này đi. Do đó với các ứng dụng nhiều luồng truy cập thì phải nâng maximum connection pool lên 1000 hoặc hơn, tùy vào stress testing thôi. Còn cái chuyện connection pool tức là nó dùng connection xong thì nó trả về pool cho thread khác sử dụng thôi.
ConnectionPool ở application mà mở 1000 nghe sai sai.
Nói như này thôi mai mốt anh đừng dùng private class member nữa, public hết member luôn. Đợi vào code review xem thằng dev nào access đến member nào không đúng thì bắt lỗi nó.Còn chuyện đảm bảo để developer ko gọi sai là thuộc về code review. Anh dùng Repository Pattern cũng ko tránh đươc.
Nói như này thôi mai mốt anh đừng dùng private class member nữa, public hết member luôn. Đợi vào code review xem thằng dev nào access đến member nào không đúng thì bắt lỗi nó.
Tôi lội rồi anh à. Tôi không bàn đến vấn đề repo và dbcontext nữa. Nó đã được bàn đủ rồi. Tôi chỉ nói đến cách lập luận này của anh thôi.Anh lội page từ từ, đặc biệt là những page cuối rồi hãy lao vào vật tôi.
Lúc đó tôi với a kia vật nhau là vì view của tôi đang nói chuyện abstract query/command. Trong khi view của a ta đang nói chuyện abstract business rule.
Với logic này của anh, thì anh hãy public hết member như tôi nói đi. Private làm gì, dev bựa nó cũng biết tự tạo 1 public member để có thể access đến cái private member đó.Hơn nữa nếu nó muốn làm sai thì nó access truc tiep ef dek thông qua interface/repo gì hết thì muốn cản nó cũng ko dc
Tôi lội rồi anh à. Tôi không bàn đến vấn đề repo và dbcontext nữa. Nó đã được bàn đủ rồi. Tôi chỉ nói đến cách lập luận này của anh thôi.
Với logic này của anh, thì anh hãy public hết member như tôi nói đi. Private làm gì, dev bựa nó cũng biết tự tạo 1 public member để có thể access đến cái private member đó.
=> Tôi cũng thế hệ 8x nên ko trẻ đâu a. Tôi làm từ Ado.Net, Nhibernate, EF đời đầu tới giờCác anh còn trẻ nên khi các anh bắt đầu code, các anh tiếp cận với EF và vì thằng EF nó làm việc theo cách của nó như các anh đang thấy. Và các anh nghĩ nó là cả thế giới.
=> Đọc lại nha tôi ko có nói nó là ko cần thiết. Anh xài 3 layers thì anh có Repository DDD chứa đám này. Tôi xài 2 layers thì tôi query trực tiếp và có khả năng code bị lặp như tôi trả lời a trên kia. Đây ko phải là vấn đề tôi chỉ trích.Rồi các anh quay lại chửi Repository Pattern như các hàm GetById, GetByName là ko cần thiết. Các anh đang bắn đại bác vào lịch sử phát triển phần mềm với tri kiến của các anh đấy.
=> Đọc lại luôn là tôi ko nói Repository/Unit of Work là sai tôi chỉ nói xài ORM nó có support. Nhiberante có cái session đó, anh muốn Unit of Work thì anh dùng thằng ISession đó trên service để BeginTransaction/Commit/Rollback. Anh muốn ko depenency trên ISession này thì anh dùng AOP để move cái đoạn wrap transaction này ra ngoài. Toàn bộ logic về commit/rollback được gọi tự động chứ ko cần phải đẽ ra cái class IUnitofWork. Còn trong service anh vẫn dùng Repository.GetById.. bình thường. Tôi hiểu cái Repository của a đang xài là dạng Repository DDD nên nó ko có gì sai cả.Tui đã đưa ví dụ với NHibernate Session rồi. Các anh muốn biết thì thử học nó đi. Khi các anh làm việc với NHibernate Session thì các anh mới hiểu thế nào là Unit Of Work.
Và vì là Unit Of Work nên cần các hàm GetById để gói gọn và chấm dứt
Session/Transaction trong một Unit Of Work để nó không ảnh hưởng đến các tác vụ khác.
Tui ko phải chuyên gia Ef, nhưng hồi còn làm NHibernate thì trong 1 UnitOfWork tôi có thể gởi đồng thời nhiều query lên server cùng một thời điểm để tránh round trip rất hay. Mà giờ già rồi ko nhớ nó gọi là gì.
Và đó là cách làm việc của các ORM thời đó. (Và bây giờ?)
. Cho tới khi thằng EF ra đời. Nó hoạt động theo một cách hoàn toàn khác để tracking changes của Entity và loại bỏ khái niệm Session (hoặc nó có internal Session tui ko rành) nên Unit Of Work nó ko có ý nghĩa trong EF.
=> Chẳng có cái khác biệt nào ở đây cả. Tôi hiểu Repository DDD là chưa logic query/ business rule thì anh tạo singleton bình thường. Nhưng ai lại để singleton cho Repository…Một cái khác biệt lớn nhất khi làm việc với Ef là Repository không khởi tạo Singleton được. Trong khi NHibernate thì tạo Singleton Repository bình thường.
Anh dùng luận điểm đó để support cho việc không cần thiết dùng repo. Tôi bác bỏ luận điểm của anh thì anh lại bảo tôi bắt bẽ và không cãi. Khi tranh luận, không phục thì anh cứ nói anh không phục, cớ chi phải bảo tôi bắt bẻ, nào rồi nói kháy anh chịu thua.Dev bựa thì nó tạo luôn cái hàm Update/Delete trong cái Repo luôn đấy. Lúc đó thì các anh có quy định Repo đó chỉ readonly ko thì cũng đâu cản dc nó. Bởi vậy có thím kia mới nói là ràng buộc cứng ở tầng db luôn ấy.
Mà thôi tôi ko cãi cái chuyện này. A bắt bẽ tôi vì câu nói đó thì tôi chịu thua.
via theNEXTvoz for iPhone
Anh dùng luận điểm đó để support cho việc không cần thiết dùng repo. Tôi bác bỏ luận điểm của anh thì anh lại bảo tôi bắt bẽ và không cãi. Khi tranh luận, không phục thì anh cứ nói anh không phục, cớ chi phải bảo tôi bắt bẻ, nào rồi nói kháy anh chịu thua.
Tôi không tranh luận với anh nữa. Vì tranh luận kiểu này anh nói gà thành vịt, vịt thành gà cũng chẳng ai nói anh sai được.