[英]Generic Repository for SQLite-Net in Xamarin Project
我想知道是否有辦法為我的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<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);
}
}
這是一個老問題,但這是我的實現。
我使用異步連接,因為它們在移動項目中提供更好的性能。 我安裝的塊是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<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);
}
}
有關如何使用它的一些示例:
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);
如果存儲庫不滿足您的查詢需求,您可以使用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();
}
我在團結IOC的幫助下實現了我的實現,我的項目包括PCL,Xamarin Android和Xamarin iOS項目
使用主鍵定義基本模型
public class BaseModel
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
}
定義通用基本存儲庫,如下所示
public interface IBaseRepository<T> : IDisposable
where T :BaseModel, new()
{
List<T> GetItems();
T GetItem(int id);
int GetItemsCount();
int SaveItem(T item);
int SaveAllItem(IEnumerable<T> items);
}
public class BaseRepository<T> : BaseRepository<T> where T : BaseModel, new()
{
private static readonly object locker = new object();
protected SQLiteConnection DatabaseConnection;
public BaseRepository(string dbPath)
{
DatabaseConnection = new SQLiteConnection(dbPath);
DatabaseConnection.CreateTable<T>();
}
public List<T> GetItems()
{
lock (locker)
{
return DatabaseConnection.Table<T>().ToList();
}
}
public int GetItemsCount()
{
lock (locker)
{
return DatabaseConnection.Table<T>().Count();
}
}
public T GetItem(int id)
{
lock (locker)
{
return DatabaseConnection.Table<T>().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);
}
}
}
}
定義從BaseModel繼承的兩個樣本類
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<IBaseRepository<Entity1>>(new BaseRepository<Entity1>(DatabasePath));
Container.RegisterInstance<IBaseRepository<Entity2>>(new BaseRepository<Entity2>(DatabasePath));
像這樣解決
using (var repo1 = App.Container.Resolve<IBaseRepository<Entity2>>())
{
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.