Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Repository pattern and one to many relationship

I am creating an application in which I use Entity Framework. I have 2 classes with one-to-many relation .I decided to use a design pattern Repository as far as I know it is a good practice. My Interface:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace DataAccess.Repository
{
   public interface IRepository<T>
   {
       void Insert(T entity);
       void Delete(T entity);
       IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
       IEnumerable<T> GetAll();
       T GetById(int id);
   }
}

My class

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using DataAccess.Repository;

namespace DataAccess
{
    public class Repository<T> : IRepository<T>  where T : class
    {
        protected DbSet<T> DbSet;

        public Repository(DbContext datacontext)
        {
            //DbContext.Set Method (Type)
            //Returns a non-generic DbSet instance for access to entities of the given type in the context and the underlying store.
            DbSet = datacontext.Set<T>();
        }

        public void Insert(T entity)
        {
            DbSet.Add(entity);
        }

        public void Delete(T entity)
        {
            DbSet.Remove(entity);
        }

        public IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate)
        {
            return DbSet.Where(predicate);
        }

        public IEnumerable<T> GetAll()
        {
            return DbSet;
        }

        public T GetById(int id)
        {
            return DbSet.Find(id);

        }
    }
}

And this is my two model classes

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Model
{
    public class Book
    {

        public int BookId { get; set; }
        public string Name { get; set; }
        public string Author { get; set; }
        public string Ganre { get; set; }
        public int Size { get; set; }
        public string Path { get; set; }

    }
}

and

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Model
{
    public  class Category{

        public Category()
        {
            Books = new List<Book>();
        }
        public int CategoryId { get; set; }
        public string CategoryName { get; set; }
        virtual public ICollection<Book> Books { get; set; } 
       }
}

But my question is, how to add the book to a category? This is an example of my implementation but book is not added to the category. But when I want to get all the books or all categories everything works fine.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.Entity;
using Model;
using DataAccess;
namespace TestDB
{
    class Program
    {
        static void Main(string[] args)
        {
            Database.SetInitializer(
                new DropCreateDatabaseIfModelChanges<BookShelfContext>());

            using (var db = new BookShelfContext())
            {
                var book = new Book
                {
                    Author = "Author Name",
                    Ganre = "Ganre",
                    Name = "Book Name",
                    Path = @"Path",
                    Size = 10
                };
                var category = new Category
                {
                    CategoryName = "Interesting"
                };


                var bookrepository = new Repository<Book>(db);
                var categoryrepository = new Repository<Category>(db);

                IEnumerable<Book> books = bookrepository.GetAll();
                IEnumerable<Category> categories = categoryrepository.GetAll();
                //get all books for example
                foreach (var b in books)
                {
                    Console.WriteLine(b.Name);
                }

            }
            Console.ReadKey();
        }
     }
 }

Thank you very much for your help. Have a nice day and less bugs)

like image 687
Qwerty Qwerty Avatar asked Nov 01 '22 08:11

Qwerty Qwerty


1 Answers

Add the context to your Repository so that you can implement the SaveChanges method:

protected readonly DbContext context;

    public Repository(DbContext datacontext)
    {
        DbSet = datacontext.Set<T>();
        context = datacontext;
    }

    public void SaveChanges()
    {
        context.SaveChanges();
    }

Then in order to add a book to an existing BookCategory simply add the book to the Category's collection and save the category:

var categoryrepository = new Repository<Category>(db);
var myCategory = categoryrepository.GetById(1);
myCategory.Books.Add(book);
categoryrepository.SaveChanges();

Remember to call SaveChanges in order to persist the data in the database. EF is smart enough to notice that you added a child to the category and it will mark it as Added. On saving changes it will insert it to the database together with the foreign keys that it needs.

like image 156
Jakub Rusilko Avatar answered Nov 08 '22 07:11

Jakub Rusilko