2009-08-25 34 views
13

Đây phải là một câu hỏi đơn giản. Đưa ra một tiêu chí, làm thế nào một trong những xóa các thực thể đáp ứng các tiêu chí?Làm cách nào để xóa đối tượng NHibernate bằng cách sử dụng tiêu chí?

Lý do:

HQL và tiêu chí NH là NHibernate cấu trúc cụ thể và như vậy họ là phía máy chủ Dal chi tiết thực hiện. Tôi không muốn họ "rò rỉ" cho phía khách hàng. Vì vậy, phía máy khách của chúng tôi cung cấp các biểu thức LINQ cho máy chủ để xử lý. Cho đến bây giờ các yêu cầu trong đó yêu cầu chọn và LINQ để NHibernate đối phó với họ chỉ là tốt.

Tuy nhiên, có nhu cầu thực hiện thao tác xóa hàng loạt ngay bây giờ. Như thường lệ, phía máy khách cung cấp một biểu thức LINQ và máy chủ là xóa các thực thể thỏa mãn biểu thức. Thật không may, LINQ to NHibernate là không có sự giúp đỡ ở đây. Điều quan trọng nhất có thể làm là dịch biểu thức LINQ đã cho thành tiêu chuẩn NHibernate.

Dù sao, đây là câu chuyện. Tôi muốn nhấn mạnh rằng phía khách hàng là không biết NHibernate ở tất cả và tôi thích nó ở lại theo cách này.

P.S.

Tôi đang sử dụng NH 2.1

Trả lời

-3

Trong kho của bạn/dao/persistencemanager/bất cứ lớp:

public IEnumerable<T> FindAll(DetachedCriteria criteria) 

     { 

      return criteria.GetExecutableCriteria(Session).List<T>(); 

     } 

và sau đó bài

public void Delete(DetachedCriteria criteria) 

     { 

      foreach (T entity in FindAll(criteria)) 

      { 

       Delete(entity); 

      } 

     } 

Xem Davy Brion của Data Access with NHibernate.

Sửa:

Theo như tôi biết, nếu bạn muốn sử dụng Tiêu chuẩn bạn cần phải nạp các đối tượng và lặp qua chúng để xóa chúng. Hoặc sử dụng HQL hoặc chuyển SQL vào phiên.

+6

Tôi không thích phương pháp này mặc dù khi làm việc với số lượng lớn các đối tượng vì nó yêu cầu tìm nạp tất cả các thực thể từ cơ sở dữ liệu đầu tiên trước khi chúng có thể bị xóa. –

+3

Điều này là đúng, bạn không phải sử dụng HQL để phát hành câu lệnh SQL 'DELETE FROM WHERE'? – DanB

+2

Các bạn, bạn không nghiêm túc. Phải có cách tốt hơn! – mark

7

Bạn có thể sử dụng các tiêu chí để chọn ID của các yếu tố của bạn, tham gia chúng trong một chuỗi và sử dụng HQL để xóa chúng?

Cái gì như:

public void Delete(ICriteria criteria, string keyName, string tableName) 
{ 
    criteria.setProjection(Projections.Attribute(keyName)); 
    IList<int> itemIds = criteria.List<int>(); 

    string collection = string.Join(",", Array.ConvertAll<int, string>(itemIds, Convert.ToString)); 

    Session.HQL(string.Format("delete from {0} where {1} in ({2})", tableName, keyName, collection); 
} 

Mã này đã không được thử nghiệm hoặc biên dịch (đặc biệt là tôi không chắc chắn của bộ phận HQL), nhưng tôi nghĩ rằng bạn có ý tưởng: chúng ta không lấy toàn bộ đối tượng nhờ vào phép chiếu, nhưng chỉ có các chỉ số.

+1

Có nghĩa là hai chuyến đi khứ hồi đến cơ sở dữ liệu? Nếu có, thì nó không đủ tốt, bởi vì SQL nguyên gốc chỉ đơn giản là trong một. – mark

+1

Vẫn tốt hơn N + 1… Tôi không thể hình dung một cách tốt hơn bằng cách sử dụng tiêu chí:/ – madprog

3

Chỉ cần đặt, cho đến 2.1.2 bạn không thể.

Tuy nhiên, nếu bạn có thể dịch biểu thức LINQ thành HQL (hoặc ICriteria thành HQL) thì bạn có thể sử dụng phương thức quá tải ISession.Delete() sử dụng chuỗi HQL đã qua.

+0

Tôi biết tôi có thể, nhưng không có vẻ lạ rằng LINQ to NHibernate dịch LINQ thành Tiêu chí thay vì HQL, mặc dù sau này được cho là mạnh hơn? Có thể nó không phải là đơn giản sau khi tất cả. Tôi rất thích nhìn thấy một nguyên mẫu làm việc ... – mark

+0

tôi sẽ không thực sự nói rằng HQL là mạnh hơn Tiêu chí, hoặc ngược lại. Chúng chỉ là hai cấu trúc khác nhau, thường là với các mục đích khác nhau: HQL cho các truy vấn và tiêu chí cụ thể một lần để xây dựng các truy vấn tránh tất cả các chuỗi ghép nối phức tạp, hỗ trợ mô đun qua DetachedCriteria và vẫn gần bản đồ của bạn hơn. Cấu trúc ví dụ cũng ngọt ngào nhưng thực tế hiếm khi được sử dụng. Nhưng dù sao, tôi không sử dụng LINQ cho nhibernate -yet- vì vậy tôi không có bất kỳ ví dụ để cung cấp cho. Tuy nhiên, cho đến khi phiên bản mới hơn hỗ trợ những gì bạn muốn, Tiêu chí chỉ dành cho các câu lệnh chọn – Jaguar

-5

Tôi biết đây là câu hỏi cũ nhưng vì lợi ích đối số; nếu có ai sử dụng mô hình kho bạn có thể khai báo một phương pháp xóa mà thực hiện như sau:

public void Delete(System.Linq.Expressions.Expression<System.Func<TEntity, bool>> predicate) 
{ 
    var entities = _session.Query<TEntity>().Where(predicate); 
    foreach (var entity in entities) 
     _session.Delete(entity); 
} 

Note mã được sử dụng biểu thức để cho giao diện kho lưu trữ phải đủ generic vì vậy bạn cũng có thể thực hiện một ví dụ kho Entity Framework.

+4

Không hoàn toàn. Những gì bạn làm là sử dụng một biểu thức để tìm nạp các thực thể và sau đó bạn xóa chúng từng cái một. Đây không phải là xóa các thực thể theo biểu thức. Những gì tôi có nghĩa là có một API bản địa mà nhận được một biểu thức, chuyển đổi nó để tuyên bố xóa SQL tương ứng và sau đó xóa tất cả các thực thể trong một đi. – mark

+2

Điều này cần một cảnh báo lớn về cách nó sẽ không được tốt đẹp khi bạn có rất nhiều đối tượng. –

Các vấn đề liên quan