【问题标题】:Database handler globally as Singleton pattern in xamarin forms全局数据库处理程序作为 xamarin 表单中的单例模式
【发布时间】:2019-03-19 06:35:44
【问题描述】:

我正在开发一个应用程序,它具有本地数据库以提供离线支持。所以我正在使用 Sqlite.net.pcl 插件,它适用于每个类模型的所有创建、插入、更新和删除表。

但我没有为每个 Model 类创建单独的数据库活动,如插入、获取、更新,而是尝试研究通用数据库处理程序 (DatabasHandler.cs) 的单例模式。

这是我尝试锻炼单例模式的代码,

public void CreateTable<T>() where T : new()
{
    var myClass = new T();
    myDatabase.CreateTableAsync<T>().Wait();
}

我像这样从 EmployeeViewModel 类中调用了这个函数;

App.Database.CreateTable<EmployeeModel>();

这里的 EmployeeModel 是一个模型类,它工作得很好,上面的函数也成功地创建了一个员工表。以同样的方式从每个 ViewModel 中创建其余的表,就像这样;

App.Database.CreateTable<SalaryModel>(); // call from SalaryViewModel Page
App.Database.CreateTable<EmployeeAttendanceModel>(); // call from AttendanceViewModel Page

下一步: 那么如何使用相同的(创建表)单例模式将所有列表项插入并获取到 DatabaseHandler.cs 中。我的问题是;

  1. 我应该如何在 DatabaseHandler.cs(Singleton 类)中创建插入/获取/更新列表的方法?
  2. 我应该如何从其视图模型中调用这些方法(插入/获取/更新)? 请帮帮我,

【问题讨论】:

    标签: xamarin xamarin.forms


    【解决方案1】:

    现在我在我的旧 XF 应用程序中有一个类似的东西,这就是我实现单例的方式,这也将回答你的第一个问题:

    我应该如何在 DatabaseHandler.cs(Singleton 类)中创建插入/获取/更新列表的方法?

    public class DatabaseHandler: IDisposable
    {
    private SQLiteConnection conn;
    //public static string sqlpath;
    private bool disposed = false;
    
    private static readonly Lazy<DatabaseHandler> database = new Lazy<DatabaseHandler>(() => new DatabaseHandler());
    private DatabaseHandler() { }
    public static DatabaseHandler Database
    {
        get
        {
            return database.Value;
        }
    }
    
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    
    protected virtual void Dispose(bool disposing)
    {
        if (disposed)
            return;
    
        if (disposing)
        {
            Dispose();
        }
    
        disposed = true;
    }
    
    public bool InitDatabase()
    {
        var ifExist = true;
        try
        {
            this.CreateDatabase();
    
            ifExist = TableExists(nameof(LocationModel), conn);
            if (!ifExist)
                this.CreateTable<LocationModel>();
    
    
            return true;
        }
    
        catch (Exception ex)
        {
            return false;
        }
    }
    
    public static bool TableExists(String tableName, SQLiteConnection connection)
    {
        var cmd = connection.CreateCommand("SELECT name FROM sqlite_master WHERE type = 'table' AND name = @name", new object[] { tableName });
        //cmd.CommandText = "SELECT * FROM sqlite_master WHERE type = 'table' AND name = @name";
        //cmd.Parameters.Add("@name", DbType.String).Value = tableName;
    
        string tabledata = cmd.ExecuteScalar<string>();
        return (cmd.ExecuteScalar<string>() != null);
    }
    public SQLiteConnection GetConnection()
    {
        var sqliteFilename = "xamdblocal.db3";
        string documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
        var path = Path.Combine(documentsPath, sqliteFilename);
        Console.WriteLine(path);
        if (!File.Exists(path)) File.Create(path);
        //var plat = new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid();
        var conn = new SQLiteConnection(path);
        // Return the database connection 
        return conn;
    }
    
    private bool CreateDatabase()
    {       
        conn = GetConnection();
        string str = conn.DatabasePath;
        return true;
    }
    
    public bool CreateTable<T>()
        where T : new()
    {
        conn.DropTable<T>();
        conn.CreateTable<T>();
        return true;
    }
    
    public bool InsertIntoTable<T>(T LoginData)
        where T : new()
    {
        conn.Insert(LoginData);
        return true;
    }
    
    public bool InsertBulkIntoTable<T>(IList<T> LoginData)
       where T : class //new()
    {
        conn.InsertAll(LoginData);
        return true;
    }    
    
    public List<T> SelectDataFromTable<T>()
      where T : new()
    {
        try
        {
            return conn.Table<T>().ToList();
        }
    
        catch (Exception ex)
        {
            return null;
        }
    }
    
    public List<T> SelectTableDatafromQuery<T>(string query)
        where T : new()
    {
        return conn.Query<T>(query, new object[] { })
                    .ToList();
    }
    
    public bool UpdateTableData<T>(string query)
        where T : new()
    {
        conn.Query<T>(query);
        return true;
    }
    
    public void UpdateTableData<T>(IEnumerable<T> query)
        where T : new()
    {
        conn.UpdateAll(query);
    }
    
    public void UpdateTableData<T>(T query)
       where T : new()
    {
        conn.Update(query);
    }   
    
    public bool DeleteTableData<T>(T LoginData)
    {
        conn.Delete(LoginData);
        return true;
    }
    
    public bool DeleteTableDataFromPrimaryKey<T>(object primaryKey)
    {
        conn.Delete(primaryKey);
        return true;
    }
    
    public bool DeleteTableDataFromQuery<T>(string query)
        where T : new()
    {
        conn.Query<T>(query);
        return true;
    }
    }
    

    我应该如何从其视图模型中调用这些方法(插入/获取/更新)?请帮帮我,

    现在例如:您想在本地数据库中插入位置的经纬度,您的本地模型看起来像这样:

    public class LocationModel
    {
        [AutoIncrement, PrimaryKey]
        public int Id { get; set; }
    
        public double Latitude { get; set; }
    
        public double Longitude { get; set; }
    
        public string Address { get; set; }
    }
    

    所以首先你要做的是创建一个 LocationModel 的实例,如下所示:

    var locationModel = new LocationModel
            {
                Latitude = location.Latitude,
                Longitude = location.Longitude
            };
    
    Then insert it something like this:
    
    DatabaseHandler.Database.InsertIntoTable<LocationModel>(locationModel);
    

    另外,不要忘记在您的项目中添加 SQLiteNetExtensions 以获得 Linq 支持。

    Goodluck 如有疑问请随时回复

    【讨论】:

    • 谢谢@G.hakim 我试过你的代码它的工作除了,这是我得到的错误,当我从我的视图模型中调用这个方法 public List SelectDataFromTable() 跨度>
    • 错误是无法将系统线程任务隐式转换为 system.collection.Generics
    • 我正在调用这个方法,例如employeeDBList = App.Database.SelectDataFromTable();我的模型也是 List 所以我改变了这样的方法 public Task> SelectDataFromTable() where T : new() in DatabaseHandler.cs
    • 如果你想使用异步类型使用 SqliteAsync,我认为你不能这样做!
    • 添加employeeDBList = await App.Database.SelectDataFromTable();时错误消失了
    猜你喜欢
    • 2016-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 1970-01-01
    • 2019-10-26
    相关资源
    最近更新 更多