Repository Design Pattern

14 בApril 2015

הרבה זמן לא הייתי באזור הזה של לכתוב על תבניות עיצוב בעברית אבל יצא לי לאחרונה לחשוב ולהתעסק הרבה מול מנגנוני DB אז מנצל את ההזדמנות להרחיב את הסדרה שלי על תבניות עיצוב בתכנה והפעם על Repository.

כרעיון הוא פשוט מאוד ולא מורכב:

יש לנו שכבת נתונים,

יש לנו ממשק לוגי שצורך את שכבת הנתונים,

לא תמיד המבנה שלנו בקוד עבור האובייקטים הוא זהה למבנה שלהם ברמת בסיס הנתונים,

לדוגמא שדות שונים, טבלאות עזר, ענייני אבטחה ותאימות, גרסאות שונות של נתונים

היינו מאוד רוצים ששכבת התכנה תוכל לרוץ בצורה נוחה למשתמש (המתכנת) מול שכבת הנתונים ובנוסף גם להרוויח ענייני תחזוקה ואבטחה כמו כל דוגמא אחרת של הפרדה לשכבות.

או כתיבת UnitTesting , עבודה מול Mock וכו’.

בנוסף אם נכתוב תשתית בצורה גנרית , נוכל להשתמש בתבנית עבור סוגים שונים של ישויות במבנה הנתונים.

דוגמא: אני יוצר מבנה נתונים בסיסי עבור טבלת Persons דרך EF :

image

הערה:

ניתן גם לומר שעבודה מול Entity Frameworkעצמו זה סוג של Repository, כי אנו עובדים מול שכבת הפרדה שנוצרת בקוד ולא מכירים פיזית את הDB.

בכל מקרה,

נגדיר חוזה בסיסי עבור כל ישות שנרצה לעבוד מולה (במקרה הזה IEntity בלי הרבה משמעות)

וקלאס מינימלי שמהווה מימוש של החוזה הנ”ל:

internal class PocoPerson : IEntity

    {

        public string Name { get; set; }


        public int Id { get; set; }


        public PocoPerson()

        {


        }

  }

עכשיו לרעיון המרכזי, נרצה לומר שהתכנה שלנו פעילה מול דבר כזה:

internal interface IRepository<T> where T : IEntity

{

    IEnumerable<IEntity> Collection { get; }


    void Add(IEntity entity);


    void Delete(IEntity entity);

}

או אז לא חשוב מי יספק לנו את המימוש בזמן ריצה.

לדוגמא התקשרות למבנה הנתונים שהגדרנו בהתחלה:

internal class DataContext : IRepository<PocoPerson>

    {

        public DataContext()

        {

            using (var context = new PersonsModelContainer())

            {

                Person DBPerson = new Person() { Id = 6, Name = "JJ" };

                context.PersonSet.Add(DBPerson);


                context.SaveChangesAsync();

            }

        }



        public IEnumerable<IEntity> Collection

        {

            get

            {

                List<PocoPerson> persons = new List<PocoPerson>();


                using (var context = new PersonsModelContainer())

                {

                    foreach (Person item in context.PersonSet)

                    {

                        PocoPerson pers = new PocoPerson() { Name = item.Name, Id = item.Id };

                        persons.Add(pers);

                    }

                }

                return persons;

            }

        }


        public void Add(IEntity entity)

        {

            throw new NotImplementedException();

        }


        public void Delete(IEntity entity)

        {

            throw new NotImplementedException();

        }

    }

וזהו, כלקוח של תכנית כזאת אני לא יודע ולא אכפת לי מה עומד מאחוריה, כל עוד אני יכול לכתוב משהו כזה:

private static void Main(string[] args)

      {

          IRepository<PocoPerson> dataRepository = new DataContext();

          var all = dataRepository.Collection;

      }

הוסף תגובה
facebook linkedin twitter email

Leave a Reply

Your email address will not be published. Required fields are marked *