문제

인스턴스 모음을 채우고 반환하는 클래스 방법을 정의하기 위해 고군분투하고 있습니다. 내가 돌아 다니는 방법을 모르는 문제는 채워야 할 개인 속성이 있다는 것입니다.

책 수업의 예를 사용합시다. 코드가 책의 가용성을 직접 설정 (예 :)하고 싶지 않습니다. 코드가 책 인스턴스에서 결제 방법을 사용해야합니다. 그래서 우리는 다음과 같은 것을 가지고 있습니다.

public class Book
{
  private int ID;
  private bool pAvailableForCheckout;

  public string Title { get; set; }
  public bool AvailableForCheckout { get { return pAvailableForCheckout } }

  // instance methods

  public Book(int BookID)
  {
     // Load book from DB by ID
  }
  public CheckOut()
  {
     // perform everything involved with checking a book out
  }
  // .. other methods like saving a book, checking out books etc.

  // class method

  public static List<Book> FindAll()
  {
     // load Dataset of books
     // foreach record in DB, use the Book(int BookID) constructor and add to List
     // return list of books
  }
}

그래서 나는 이것을 내 코드에서 사용할 수 있습니다.

foreach(Book curBook in Book.FindAll())
  { /* do something with book */ }

위 구현의 문제점은 N+1 히트를 사용하여 데이터베이스에 1 쿼리 대신 모든 책을로드해야한다는 것입니다. 이것을 어떻게 해결합니까?

나는 이것이 프로그래밍 101이라고 확신하지만 물어봐야했다.

도움이 되었습니까?

해결책

개인 속성을 직접 채우는 보호 된 생성자를 만들 수 있습니다.

다른 팁

Foreach는 이미 인스턴스화 된 개체 목록을 반복해야하며 DB에 연결할 필요가 없습니다.

DB에 대한 새로운 히트가 아닌 기존 데이터 세트에서 책을 인스턴스화 할 수 있도록 책 객체의 속성을 수용하는 생성자를 작성해야합니다.

그래서:

건설자:

public book (String title, String avail) {Title=title...}

그리고 그 방법에서

public static void FindAll()
{
List<Books> books = new List<books>();
using (Sqlconnection conn = new sqlconnection(connstring))
using (sqlcommand cmd = new SqlCommand("select title, available from book ", conn)
{
  SqlDatareader dr = cmd.executereader()
  while (dr.read())
  {
    books.add(new Book(dr["title"], dr["avail"])
  }

}

foreach(Book curBook in Book.FindAll())
  { /* do something with book */ }

}

이데올로기 적 순도에서 다소 극단적 인 예를 들어 :

먼저, ID가 주어진 데이터베이스에서 T 형 객체를 검색 할 수있는 클래스의 인터페이스입니다.

interface IAdapter<T>
{
   T Retrieve(int id);
}

이제 Book 더 이상 공개 생성자를 노출시키지 않고 대신 IAdapter<Book> 데이터베이스에서 책을 검색하려면 :

public class Book
{
    public static IAdapter<Book> Adapter { get; set; }

    public static Book Create(int id)
    {
       return Adapter.Retrieve(id);
    }

    // constructor is internal so that the Adapter can create Book objects
    internal Book() { }

    public int ID { get; internal set; }
    public string Title { get; internal set; }
    public bool AvailableForCheckout { get; internal set; }

}

클래스 구현을 작성해야합니다 IAdapter<Book> 자신과 할당 Book.Adapter 그것을 위해 Book.Create() 데이터베이스에서 물건을 가져올 수 있습니다.

나는이 디자인이 우려의 꽤 엄격한 분리를 시행하기 때문에 "이데올로기 순도"라고 말합니다. Book 데이터베이스와 대화하는 방법을 알고있는 클래스 - 심지어 ~이다 데이터베이스.

예를 들어, 다음은 가능한 한 가지 구현이 있습니다 IAdapter<Book>:

public class DataTableBookAdapter : IAdapter<Book>
{
   public DataTable Table { get; set; }
   private List<Book> Books = new List<Book>();

   Book Retrieve(int id)
   {
      Book b = Books.Where(x => x.ID = id).FirstOrDefault();
      if (b != null)
      {
         return b;
      }

      BookRow r = Table.Find(id);
      b = new Book();

      b.ID = r.Field<int>("ID");
      b.Title = r.Field<string>("Title");
      b.AvailableForCheckout = r.Field<bool>("AvailableForCheckout");

      return b;
   }
}

다른 클래스는 DataTable 이 수업은 사용합니다. a를 사용하는 다른 구현을 쓸 수 있습니다 SqlConnection 데이터베이스와 직접 대화합니다.

당신은 이것을 쓸 수도 있습니다 :

public IAdapter<Book> TestBookAdapter : IAdapter<Book>
{
   private List<Book> Books = new List<Book>();

   public TestBookAdapter()
   {
      Books.Add(new Book { ID=1, Title="Test data", AvailableForCheckout=false };
      Books.Add(new Book { ID=2, Title="Test data", AvailableForCheckout=true };
   }

   Book Retrieve(int id)
   {
      return Books.Where(x => x.ID == id);
   }
}

이 구현은 데이터베이스를 전혀 사용하지 않습니다. Book 수업.

이 두 클래스는 개인을 유지합니다 List<Book> 재산. 이것은 당신이 전화 할 때마다 보장합니다 Book.Create() 주어진 ID로, 당신은 똑같이 돌아갑니다 Book 사례. 이것을 Book 대신 클래스 - 정적 개인을 만들 것입니다 List<Book> 속성 Book 그리고 논리를 작성하십시오 Create 방법을 유지합니다.

데이터를 데이터베이스로 다시 푸시하기 위해 동일한 접근 방식을 사용합니다. Update, Delete, 그리고 Insert 방법 IAdapter<T> 어댑터 클래스에서 구현하고 Book 적절한 시간에 해당 방법을 호출하십시오.

SQL Where Statement를 사용하여 데이터베이스 측에서 책의 가용성을 확인하지 않겠습니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top