2009-03-07 31 views
5

Cách được khuyến nghị để trả lại dữ liệu ad hoc (tùy chỉnh từng trường hợp) từ kho lưu trữ nào không phù hợp với bất kỳ thực thể mô hình nào hoặc mở rộng một số?Dữ liệu đặc biệt và mẫu kho lưu trữ

Ví dụ 101 sẽ là ứng dụng từ xin chào mọi nơi: hệ thống blog. Giả sử bạn muốn tải danh sách các bài đăng có mục nhập bài đăng có một số thông tin bổ sung không tồn tại trong thực thể Bài đăng. Giả sử đó là số lượng nhận xét và ngày và giờ của nhận xét cuối cùng. Điều này sẽ rất tầm thường nếu một người đang sử dụng SQL cũ và đọc dữ liệu trực tiếp từ cơ sở dữ liệu. Làm thế nào tôi có thể làm điều đó một cách tối ưu bằng cách sử dụng mẫu kho lưu trữ nếu tôi không thể đủ khả năng tải toàn bộ các bộ sưu tập các Nhận xét cho mỗi Bài đăng và tôi muốn thực hiện nó trong một lần truy cập cơ sở dữ liệu? Có mô hình thường được sử dụng cho tình huống này không? Bây giờ hãy tưởng tượng rằng bạn có ứng dụng web phức tạp vừa phải trong đó mỗi trang cần một dữ liệu tùy chỉnh hơi khác nhau và không thể tải toàn bộ hệ thống phân cấp (yêu cầu về hiệu suất, bộ nhớ, v.v.).

Một số ý tưởng ngẫu nhiên:

  1. Thêm một danh sách các thuộc tính cho mỗi mô hình có thể được dân cư của các dữ liệu tùy chỉnh.

  2. Thực thể mô hình lớp con theo từng trường hợp và tạo trình đọc tùy chỉnh cho từng lớp con.

  3. Sử dụng LINQ, soạn các truy vấn đặc biệt và đọc các lớp ẩn danh.

Lưu ý: Tôi đã hỏi similar question recently nhưng có vẻ quá chung chung và không thu hút được nhiều sự chú ý.

Ví dụ:

Dựa trên gợi ý trong câu trả lời dưới đây, tôi đang bổ sung thêm một ví dụ cụ thể hơn. Dưới đây là tình hình tôi đã cố gắng để mô tả:

IEnumarable<Post> posts = repository.GetPostsByPage(1); 
foreach (Post post in posts) 
{ 

    // snip: push post title, content, etc. to view 

    // determine the post count and latest comment date 
    int commentCount = post.Comments.Count(); 
    DateTime newestCommentDate = post.Comments.Max(c => c.Date); 

    // snip: push the count and date to view 

} 

Nếu tôi không làm bất cứ điều gì thêm và sử dụng một ra khỏi kệ ORM, điều này sẽ dẫn đến n + 1 thắc mắc hoặc có thể là một tải truy vấn tất cả các bài viết và bình luận . Nhưng tối ưu, tôi muốn có thể chỉ thực hiện một SQL mà sẽ trả về một hàng cho mỗi bài bao gồm tiêu đề bài viết, nội dung, vv và số lượng bình luận và ngày bình luận gần đây nhất trong cùng. Điều này là tầm thường trong SQL. Vấn đề là kho lưu trữ của tôi sẽ không thể đọc và phù hợp với loại dữ liệu này vào mô hình. Các ngày tối đa và số đếm đi đâu?

Tôi không yêu cầu cách thực hiện điều đó. Bạn luôn có thể làm điều đó bằng cách nào đó: thêm phương thức bổ sung vào kho lưu trữ, thêm lớp mới, thực thể đặc biệt, sử dụng LINQ v.v., nhưng tôi đoán câu hỏi của tôi là như sau. Làm thế nào đến mô hình kho lưu trữ và phát triển theo mô hình thích hợp được chấp nhận rộng rãi, nhưng dường như chúng không giải quyết trường hợp dường như rất phổ biến và cơ bản này.

Trả lời

0

Không thể nói rằng tôi thực sự thấy vấn đề là gì, chỉ cần bắn trong không khí ở đây:

  • Thêm một thực thể cụ thể để đóng gói các thông tin yo muốn
  • Thêm một tài sản nhận xét cho bài viết.(Tôi không hiểu tại sao điều này yêu cầu bạn tìm nạp tất cả nhận xét - bạn chỉ có thể tìm nạp nhận xét cho bài đăng cụ thể bạn đang tải)
  • Sử dụng tải chậm để chỉ tìm nạp nhận xét khi bạn truy cập vào thuộc tính

Tôi nghĩ bạn sẽ có cơ hội lớn hơn khi nhìn thấy câu hỏi của bạn được trả lời nếu bạn làm nền tảng, ngôn ngữ và trình ánh xạ O/R cụ thể (có vẻ là .NET C# hoặc VB, vì bạn đã đề cập LINQ. LINQ 2 SQL? ? Cái gì khác?)

+0

Cảm ơn bạn đã chỉ cho tôi điều đó. Tôi đã thêm một ví dụ cụ thể đơn giản và giải thích thêm. –

1

Có rất nhiều câu hỏi này. Bạn có cần dữ liệu cụ thể này cho một quy trình báo cáo không? Nếu vậy, thì giải pháp thích hợp là có quyền truy cập dữ liệu riêng biệt cho mục đích báo cáo. Cơ sở dữ liệu phẳng, lượt xem, vv.

Hoặc là một truy vấn đặc biệt cần? Nếu vậy, Ayende có một bài viết về vấn đề này rất. http://ayende.com/Blog/archive/2006/12/07/ComplexSearchingQueryingWithNHibernate.aspx

Anh ấy sử dụng đối tượng "Trình tìm kiếm". Anh ấy đang sử dụng NHibernate, vì vậy về cơ bản những gì anh ta đang làm là tạo ra một truy vấn tách rời.

Tôi đã làm điều tương tự trong quá khứ bằng cách tạo đối tượng truy vấn mà tôi có thể điền trước khi giao cho kho lưu trữ (một số thuần túy DDD sẽ tranh luận chống lại nó, nhưng tôi thấy nó thanh lịch và dễ sử dụng).

Đối tượng Query thực hiện một giao diện thông thạo, vì vậy tôi có thể viết này và nhận được kết quả trở lại:

IQuery query = new PostQuery() 
    .WithPostId(postId) 
    .And() 
    .WithCommentCount() 
    .And() 
    .WithCommentsHavingDateLessThan(selectedDate); 


Post post = _repository.Find(query); 

Tuy nhiên, trong trường hợp cụ thể của bạn tôi phải tự hỏi tại thiết kế của bạn. Bạn đang nói rằng bạn không thể tải các bình luận với bài viết. Tại sao? Bạn có quá đáng lo ngại về hiệu suất không? Đây có phải là trường hợp tối ưu hóa sớm không? (có vẻ như đối với tôi)

Nếu tôi có đối tượng Bài đăng, nó sẽ là gốc tổng hợp của tôi và nó sẽ đi kèm với các chú thích đính kèm. Và sau đó tất cả mọi thứ bạn muốn làm sẽ làm việc trong mọi tình huống.

+0

Cảm ơn bạn. Bạn gợi ý có vẻ như là một khởi đầu tốt. Tôi tự hỏi bạn thực sự lưu trữ số lượng nhận xét ở đâu? Chắc chắn, không có thành viên dữ liệu riêng biệt cho nó trong thực thể Post. –

+0

Về hiệu suất, ví dụ về các bài đăng trên blog chỉ là một ví dụ. Ứng dụng thực tế mà tôi có trong tâm trí đã chạy, và chúng tôi không thể thực sự đủ khả năng để tải toàn bộ bộ sưu tập. –

+0

Miền vấn đề thực sự tạo sự khác biệt. Không ai có thể nói nếu bạn có một lỗ hổng thiết kế với tên miền của bạn, điều này thực sự có thể dẫn đến một giải pháp tốt hơn. Bài đăng & nhận xét là một vấn đề giải quyết và các câu hỏi của bạn không mang ý nghĩa theo ngữ cảnh. –

1

Vì chúng tôi cần khẩn trương giải quyết vấn đề mà tôi đã nêu trong câu hỏi ban đầu của mình, chúng tôi đã sử dụng giải pháp sau. Chúng tôi đã thêm bộ sưu tập thuộc tính (từ điển) vào từng thực thể mô hình và nếu DAL cần, nó sẽ dính dữ liệu tùy chỉnh vào. Để thiết lập một số loại điều khiển, bộ sưu tập thuộc tính được khóa bằng các cá thể của một lớp được chỉ định và nó chỉ hỗ trợ các kiểu dữ liệu đơn giản (số nguyên, ngày tháng, ...). . Một trường hợp điển hình mà giải quyết này là: tải một thực thể với số lượng cho các bộ sưu tập con của nó thay vì các tập hợp được điền đầy đủ. Tôi nghi ngờ rằng điều này có lẽ không nhận được bất kỳ giải thưởng cho một thiết kế phần mềm, nhưng nó là giải pháp đơn giản nhất và thực tế nhất cho trường hợp của chúng tôi.

+0

Tôi nghĩ rằng tùy chọn khác sẽ được đính kèm một số truy vấn được đặt tên cho các thực thể và sử dụng các truy vấn đó trong kho. Câu hỏi thú vị mặc dù, quá xấu vì vậy ít người dường như grok nó. – wds

0

Nếu bạn không bị khóa vào RDBM thì cơ sở dữ liệu như CouchDB hoặc Amazon đơn giản có thể là một cái gì đó để xem xét. Những gì bạn mô tả là tầm thường trong một khung nhìn CouchDB. Điều này có thể không thực sự trả lời cho bạn câu hỏi cụ thể nhưng đôi khi rất tốt để xem xét các tùy chọn hoàn toàn khác nhau.

0

Đối với điều này tôi thường có một RepositoryStatus và một lớp trạng thái hoạt động như đối tượng chuyển dữ liệu của tôi (DTO). Lớp Status được sử dụng trong lớp dịch vụ ứng dụng của tôi (vì lý do tương tự) mà từ đó RepositoryStatus kế thừa. Sau đó, với lớp này tôi có thể trả về các thông báo lỗi, các đối tượng phản hồi, vv từ lớp Repository. Lớp này là chung chung ở chỗ nó sẽ chấp nhận bất kỳ đối tượng trong và bỏ nó ra cho người nhận.

Đây là lớp Tình trạng:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using RanchBuddy.Core.Domain; 
using StructureMap; 

namespace RanchBuddy.Core.Services.Impl 
{ 
    [Pluggable("Default")] 
    public class Status : IStatus 
    { 
     public Status() 
     { 
      _messages = new List<string>(); 
      _violations = new List<RuleViolation>(); 
     } 

     public enum StatusTypes 
     { 
      Success, 
      Failure 
     } 

     private object _object; 
     public T GetObject<T>() 
     { 
      return (T)_object; 
     } 
     public void SetObject<T>(T Object) 
     { 
      _object = Object; 
     } 

     private List<string> _messages; 
     public void AddMessage(string Message) 
     { 
      _messages.Add(Message); 
     } 
     public List<string> GetMessages() 
     { 
      return _messages; 
     } 
     public void AddMessages(List<string> Messages) 
     { 
      _messages.AddRange(Messages); 
     } 

     private List<RuleViolation> _violations; 
     public void AddRuleViolation(RuleViolation violation) 
     { 
      _violations.Add(violation); 
     } 
     public void AddRuleViolations(List<RuleViolation> violations) 
     { 
      _violations.AddRange(violations); 
     } 
     public List<RuleViolation> GetRuleViolations() 
     { 
      return _violations; 
     } 
     public StatusTypes StatusType { get; set; } 
    } 
} 

Và đây là RepositoryStatus:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using RanchBuddy.Core.Services.Impl; 
using StructureMap; 

namespace RanchBuddy.Core.DataAccess.Impl 
{ 
    [Pluggable("DefaultRepositoryStatus")] 
    public class RepositoryStatus : Status, IRepositoryStatus 
    { 

    } 
} 

Như bạn có thể thấy RepositoryStatus chưa làm bất cứ điều gì đặc biệt và chỉ dựa trên các đối tượng Status tiện ích. Nhưng tôi muốn bảo lưu quyền gia hạn vào một ngày sau đó!

Tôi chắc chắn rằng một số người chết ở đó sẽ nói rằng điều này không nên được sử dụng nếu bạn là một nhà tiên tri ... tuy nhiên tôi biết nỗi đau của bạn trong đó đôi khi bạn cần phải vượt qua nhiều hơn chỉ một đối tượng trả về!

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