Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
244 views
in Technique[技术] by (71.8m points)

c# - Generic Repository for SQLite-Net in Xamarin Project

I am wondering if there is a way to write a generic repository for my Xamarin project versus writing a different Repository for each entity in my object. The Xamarin Tasky Pro example have one Repository for the Task entity because that is the only entity it has.

In my own project I have more than one Entity, so my question is how can I make the following Customer Repository to become generic so that the ProductManager, EmployeeManager, etc can use it. If you know of an example or a blog post please point me to the right direction

namespace App.DataLayer
{
    public class CustomerRepository
    {
        private ProntoDatabase _db = null;
        protected static string DbLocation;
        protected static CustomerRepository Me;

        static CustomerRepository()
        {
            Me = new CustomerRepository();
        }

        protected CustomerRepository()
        {
            //set the db location;
            DbLocation = DatabaseFilePath;

            //instantiate the database
            _db = new ProntoDatabase(DbLocation);
        }


        public static string DatabaseFilePath
        {
            get
            {
                const string sqliteFilename = "CustomerDB.db3";
                var libraryPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                var path = Path.Combine(libraryPath, sqliteFilename);
                return path;
            }
        }


        // CRUD (Create, Read, Update and Delete) methods

        public static Customer GetCustomer(int id)
        {
            return Me._db.GetItem<Customer>(id);
        }

        public static IEnumerable<Customer> GetCustomers()
        {
            return Me._db.GetItems<Customer>();
        }

        public static int SaveCustomer(Customer item)
        {
            return Me._db.SaveItem(item);
        }

        public static int DeleteCustomer(int id)
        {
            return Me._db.DeleteItem<Customer>(id);
        }
    }
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This is an old question but here is my implementation.

I′m using async connections as they provide better performance in mobile projects. The nuggets I installed are Sqlite.Net-PCL/SQLite.Net.Async-PCL on the Core project and the corresponding nuget on the Android project.

My Repository looks like this:

using System;
using System.Collections.Generic;
using Core.Models;
using SQLite.Net;
using System.Linq;
using SQLite.Net.Async;
using System.Threading.Tasks;
using System.Linq.Expressions;

namespace Core.Managers
{
    public interface IRepository<T> where T : class, new()
    {
        Task<List<T>> Get();
        Task<T> Get(int id);
        Task<List<T>> Get<TValue>(Expression<Func<T, bool>> predicate = null, Expression<Func<T, TValue>> orderBy = null);
        Task<T> Get(Expression<Func<T, bool>> predicate);
        AsyncTableQuery<T> AsQueryable();
        Task<int> Insert(T entity);
        Task<int> Update(T entity);
        Task<int> Delete(T entity);
    }

    public class Repository<T> : IRepository<T> where T : class, new()
    {
        private SQLiteAsyncConnection db;

        public Repository(SQLiteAsyncConnection db)
        {
            this.db = db;
        }

        public AsyncTableQuery<T> AsQueryable() => 
            db.Table<T>();

        public async Task<List<T>> Get() => 
            await db.Table<T>().ToListAsync();

        public async Task<List<T>> Get<TValue>(Expression<Func<T, bool>> predicate = null, Expression<Func<T, TValue>> orderBy = null)
        {
            var query = db.Table<T>();

            if (predicate != null)
                query = query.Where(predicate);

            if (orderBy != null)
                query = query.OrderBy<TValue>(orderBy);

            return await query.ToListAsync();
        }

        public async Task<T> Get(int id) => 
             await db.FindAsync<T>(id);

        public async Task<T> Get(Expression<Func<T, bool>> predicate) =>
            await db.FindAsync<T>(predicate);

        public async Task<int> Insert(T entity) => 
             await db.InsertAsync(entity);

        public async Task<int> Update(T entity) =>
             await db.UpdateAsync(entity);

        public async Task<int> Delete(T entity) =>
             await db.DeleteAsync(entity);
    }
}

Some examples on how to use it:

var connection = new SQLiteAsyncConnection(() => sqlite.GetConnectionWithLock());
await connection.CreateTablesAsync<Ingredient, Stock>();

IRepository<Stock> stockRepo = new Repository<Stock>(connection);
IRepository<Ingredient> ingredientRepo = new Repository<Ingredient>(connection);

var stock1 = new Stock { 
    IngredientId = 1,
    DaysToExpire = 3,
    EntryDate = DateTime.Now,
    Location = StockLocations.Fridge,
    MeasureUnit = MeasureUnits.Liter,
    Price = 5.50m,
    ProductName = "Leche Auchan",
    Quantity = 3,
    Picture = "test.jpg",
    Family = IngredientFamilies.Dairy
};

var stockId = await stockRepo.Insert(stock1);

var all = await stockRepo.Get();
var single = await stockRepo.Get(72);
var search = await stockRepo.Get(x => x.ProductName.StartsWith("something"));
var orderedSearch = await stockRepo.Get(predicate: x => x.DaysToExpire < 4, orderBy: x => x.EntryDate);

If the Repository does not meet your query needs, you can use AsQueryable():

public async Task<List<Stock>> Search(string searchQuery, StockLocations location, IngredientFamilies family)
{
    var query = stockRepo.AsQueryable();

    if (!string.IsNullOrEmpty(searchQuery))
    {
        query = query.Where(x => x.ProductName.Contains(searchQuery) || x.Barcode.StartsWith(searchQuery));
    }
    if (location != StockLocations.All)
    {
        query = query.Where(x => x.Location == location);
    }
    if (family != IngredientFamilies.All)
    {
        query = query.Where(x => x.Family == family);
    }

    return await query.OrderBy(x => x.ExpirationDays).ToListAsync();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...