Xamarin项目中SQLite-Net的通用存储库

我想知道是否有办法为我的Xamarin项目编写通用存储库,而不是为我的对象中的每个实体编写不同的存储库。 Xamarin Tasky Pro示例为Task实体提供了一个Repository,因为它是它拥有的唯一实体。

在我自己的项目中,我有多个实体,所以我的问题是如何使以下客户存储库变得通用,以便ProductManager,EmployeeManager等可以使用它。 如果你知道一个例子或博客文章,请指出我正确的方向

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(id); } public static IEnumerable GetCustomers() { return Me._db.GetItems(); } public static int SaveCustomer(Customer item) { return Me._db.SaveItem(item); } public static int DeleteCustomer(int id) { return Me._db.DeleteItem(id); } } 

这是一个老问题,但这是我的实现。

我使用异步连接,因为它们在移动项目中提供更好的性能。 我安装的块是Core项目上的Sqlite.Net-PCL / SQLite.Net.Async-PCL和Android项目上的相应nuget。

我的存储库看起来像这样:

 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 where T : class, new() { Task> Get(); Task Get(int id); Task> Get(Expression> predicate = null, Expression> orderBy = null); Task Get(Expression> predicate); AsyncTableQuery AsQueryable(); Task Insert(T entity); Task Update(T entity); Task Delete(T entity); } public class Repository : IRepository where T : class, new() { private SQLiteAsyncConnection db; public Repository(SQLiteAsyncConnection db) { this.db = db; } public AsyncTableQuery AsQueryable() => db.Table(); public async Task> Get() => await db.Table().ToListAsync(); public async Task> Get(Expression> predicate = null, Expression> orderBy = null) { var query = db.Table(); if (predicate != null) query = query.Where(predicate); if (orderBy != null) query = query.OrderBy(orderBy); return await query.ToListAsync(); } public async Task Get(int id) => await db.FindAsync(id); public async Task Get(Expression> predicate) => await db.FindAsync(predicate); public async Task Insert(T entity) => await db.InsertAsync(entity); public async Task Update(T entity) => await db.UpdateAsync(entity); public async Task Delete(T entity) => await db.DeleteAsync(entity); } } 

有关如何使用它的一些示例:

 var connection = new SQLiteAsyncConnection(() => sqlite.GetConnectionWithLock()); await connection.CreateTablesAsync(); IRepository stockRepo = new Repository(connection); IRepository ingredientRepo = new Repository(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); 

如果存储库不满足您的查询需求,您可以使用AsQueryable():

 public async Task> 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(); } 

我在团结IOC的帮助下实现了我的实现,我的项目包括PCL,Xamarin Android和Xamarin iOS项目

使用主键定义基本模型

 public class BaseModel { [PrimaryKey, AutoIncrement] public int Id { get; set; } } 

定义通用基本存储库,如下所示

 public interface IBaseRepository : IDisposable where T :BaseModel, new() { List GetItems(); T GetItem(int id); int GetItemsCount(); int SaveItem(T item); int SaveAllItem(IEnumerable items); } public class BaseRepository : BaseRepository where T : BaseModel, new() { private static readonly object locker = new object(); protected SQLiteConnection DatabaseConnection; public BaseRepository(string dbPath) { DatabaseConnection = new SQLiteConnection(dbPath); DatabaseConnection.CreateTable(); } public List GetItems() { lock (locker) { return DatabaseConnection.Table().ToList(); } } public int GetItemsCount() { lock (locker) { return DatabaseConnection.Table().Count(); } } public T GetItem(int id) { lock (locker) { return DatabaseConnection.Table().Where(i => i.Id == id).FirstOrDefault(); } } public int SaveItem(T item) { lock (locker) { if (item.Id != 0) { return DatabaseConnection.Update(item); } else { return DatabaseConnection.Insert(item); } } } } 

定义从BaseModelinheritance的两个示例类

 public class Entity1 : BaseModel { public int ItemName { get; set; } } public class Entity2 : BaseModel { public int Description { get; set; } } public static UnityContainer Container { get; private set; } public static void InitializeUnityContainer() { if (Container == null) Container = new UnityContainer(); } 

寄存器

 Container.RegisterInstance>(new BaseRepository(DatabasePath)); Container.RegisterInstance>(new BaseRepository(DatabasePath)); 

像这样解决

 using (var repo1 = App.Container.Resolve>()) { }