Xamarin.FormsでEntityFramework CoreとSQLiteを使うチュートリアル メモ
空のXamarin.Formsアプリを作成
Sqliteを使ってDBを操作するためのクラスを作成
.net standardクラスライブラリとして作成する.
EntityFramework Coreはクロスプラットフォームで使えるため.
Microsoft.EntityFrameworkCore.Sqliteをインストールする
Nugetでインストールする.
インストール先のプロジェクトはAndroid,iOS,SqliteApp.Standardの3つ.
共通コードにはインストールしないんだ?
Modelを作る
共通コードにモデルを追加する.
public class Product { public int Id { get; set; } public string Title { get; set; } public decimal Price { get; set; } public override string ToString() { return $"({Id}) {Title}, {Price}"; } }
リポジトリのインターフェースを作成する
共通コードにインターフェースを追加する.
public interface IProductRepository { Task<IEnumerable<Product>> GetProductAsync(); Task<Product> GetProductByIdAsync(int id); Task<bool> AddProductAsync(Product product); Task<bool> UpdateProductAsync(Product product); Task<bool> RemoveProductAsync(int id); Task<IEnumerable<Product>> QueryProductsAsync(Func<Product,bool> predicate); }
リポジトリクラスをクラスライブラリ側に作成する
IProductRepositoryインターフェースを利用するために共通コードのプロジェクトを参照する必要がある.
実装は以下のとおり.
public class ProductRepository : IProductRepository { private readonly DataBaseContext _databaseContext; public ProductRepository(string dbPath) { _databaseContext = new DataBaseContext(dbPath); } public async Task<bool> AddProductAsync(Product product) { try { var tracking = await _databaseContext.Products.AddAsync(product); await _databaseContext.SaveChangesAsync(); var isAdded = tracking.State == EntityState.Added; return isAdded; } catch(Exception e) { return false; } } public async Task<IEnumerable<Product>> GetProductAsync() { try { var products = await _databaseContext.Products.ToListAsync(); return products; } catch(Exception e) { return null; } } public async Task<Product> GetProductByIdAsync(int id) { try { //FindAsyncは暗黙的に主キーで検索されるのか //見つからない場合はnullを返す var product = await _databaseContext.Products.FindAsync(id); return product; } catch(Exception e) { return null; } } public async Task<IEnumerable<Product>> QueryProductsAsync(Func<Product, bool> predicate) { try { var products = _databaseContext.Products.Where(predicate); return products.ToList(); } catch(Exception e) { return null; } } public async Task<bool> RemoveProductAsync(int id) { try { var product = await _databaseContext.Products.FindAsync(id); var tracking = _databaseContext.Remove(product); await _databaseContext.SaveChangesAsync(); var isDeleted = tracking.State == EntityState.Deleted; return isDeleted; } catch(Exception e) { return false; } } public async Task<bool> UpdateProductAsync(Product product) { try { var tracking = _databaseContext.Update(product); await _databaseContext.SaveChangesAsync(); var isModified = tracking.State == EntityState.Modified; return isModified; } catch(Exception e) { return false; } } }
各プラットフォームごとにフォルダのパスを取得する
各プラットフォームのプロジェクト内でそれぞれパスを取得する.
ファイルの保存に適したパスはプラットフォームごとに異なるため. プラットフォームごとのファイル保存に適したフォルダのパスとその取得についてはこちら.
Android : MainActivity.cs
var dbPath = Path.Combine(System.Environment.GetFolderPath (System.Environment.SpecialFolder.Personal), "productsDB.db"); var productsRepository = new ProductsRepository(dbPath); Xamarin.Essentials.Platform.Init(this, savedInstanceState); global::Xamarin.Forms.Forms.Init(this, savedInstanceState); LoadApplication(new App(productsRepository));
iOS : AppDelegate.cs
SQLitePCL.Batteries_V2.Init();//iOSはこれが必要らしい var dbPath = Path.Combine(Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments), "..", "Library", "products.db"); var productsRepository = new ProductsRepository(dbPath); global::Xamarin.Forms.Forms.Init(); LoadApplication(new App(productsRepository));
iOS,AndroidそれぞれのプロジェクトにSqlite.Standardプロジェクトへの参照を追加する.
もちろんAppクラスに引数を受け取るコンストラクタを作る必要がある.
Shared : App.xaml.cs
public App(IProductsRepository productsRepository) { InitializeComponent(); MainPage = new MainPage(); }
DbContextを作る
これはクラスライブラリ内に作る
public class DataBaseContext:DbContext { public DbSet<Product> Products { get; set; } private readonly string _databasePath; public DataBaseContext(string databasePath) { _databasePath = databasePath; //DBが存在しない場合は作成する. //すでにある場合は何もしない. //Migrationが行われるということか. //Database.EnsureDeleted();//これでDBが削除される Database.EnsureCreated(); } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlite($"Data Source={_databasePath}"); } }
まとめ
まとまらなかったなぁ.
基本的には以下の記事のコマンドラインアプリでSQLiteを使うのと変わらない.
- Nugetでインストールして
- モデルを作って
- DbContext作って
- EnsureCreateメソッドを実行
すれば,dbファイルが作成されて使える状態になる.
Xamarin.Forms特有の手順というと,DBファイルのパスの取得あたりだろうか.