【问题标题】:SQLite Implementation in VS 2019VS 2019 中的 SQLite 实现
【发布时间】:2020-09-14 04:52:11
【问题描述】:

我对编码和尝试制作我的第一个 WPF 应用程序仍然很陌生。过去 3 天我一直在尝试实施 sqlite。

我正在使用 VS 2019。我已经下载了 SQLite 工具箱并按照此处的说明进行操作 - https://github.com/ErikEJ/SqlCeToolbox/wiki/EF6-workflow-with-SQLite-DDEX-provider。我做了一个完整的安装。我应该将它安装在我的项目目录中吗?因为现在我只有一堆文件,而 Studio 中似乎没有任何变化。我尝试使用 Install.exe,但它返回“确认选项未启用”错误。查看一个类似的问题,我尝试将文件放在项目的外部文件夹中,然后使用 VS 开发控制台将 System.Data.SQLite.EF6.dll 安装到我的 GAC。工具箱没有看到任何变化,也无法识别 dll,而且我很难为我的版本找到可靠的信息。感谢您为正确的方向提供任何帮助!

【问题讨论】:

  • 我建议您将 SQLite Nuget 包安装到您的项目中。在“Tools\NuGet Package Manager\Manage Nuget Packages for Solution ...”菜单树下查看。然后搜索 SQLite。即使是 SQLite 的 Microsoft Entity Framework 实现,也有很多选择
  • 如果您只是追求一种简单的数据存储方式,您可以选择其中一个 PCL Net 包。我最近将 Frank Krueger 的 SQLite-net-pcl 用于 Xamarin 应用程序。它允许轻松存储类类型。
  • 我想我只是不完全确定我“需要”什么才能让它工作。这将是一个 ERP 系统,有很多表格和数据输入。我只需要它来查看数据库,我之前已经尝试过使用 nugets 并且我得到了插入 - 找不到表错误。我创建了一个带有连接的类,并使用 Environment 作为路径。除此之外没有错误,只是没有和我说话!我读到它可能与 Interoper dll 有关,但在认为我需要这个工具箱,然后是 dll,一些 Nugets 之后,我对自己需要什么感到困惑。
  • 你能贴出任何简化的DBConnection、数据文件和文件创建代码吗?

标签: c# wpf sqlite visual-studio-2019 gac


【解决方案1】:

据我所知,您以编程方式访问 SQLite 功能,我不确定您为什么提到工具箱。

我最近用于 Xamarin 项目的 NuGet 包(Frank Krueger 的 SQLite-net-pcl 和支持库)允许我使用非常简单的对象映射,而无需求助于 SQL 之类的字符串。

我在代码中使用了很多接口,但这是我的所有访问数据库类

:

   public class AllAccessDataTableBaseSqLite<T> : IDataAccessRead<T>, IDataAccessWrite<T>,IDataAccessExpressionSearch<T>, IDataAccessDelete<T> where T: IDataRecord, new()
    {
        //Note that this static value will only apply to those classes based on the same generic type e.g. all DataTableBase<User> instances etc.
        public static SQLiteAsyncConnection DBConnection;

        /// <summary>
        /// Lock object to prevent multi-thread interruption of code segment.
        /// </summary>
        public static readonly object CollisionLock = new object();

        /// <summary>
        /// Constructor
        /// </summary>
        public AllAccessDataTableBaseSqLite()
        {
            lock (CollisionLock)
            {
                if (DBConnection != null)
                {
                    DBConnection.CreateTableAsync<T>().Wait();

                    return;
                }

                try
                {
                    string directory;

                    if (DeviceInfo.Platform != DevicePlatform.Unknown)
                    {
                        directory = FileSystem.AppDataDirectory;
                    }
                    else
                    {
                        directory = "DataStore";
                        var directoryInfo = Directory.CreateDirectory(directory);
                        directory = directoryInfo.FullName;
                    }

                    var path = Path.Combine(directory, $"{typeof(T).Name}.db");
                    if (!File.Exists(path))
                    {
                        using var fileStream = File.Create(path);

                        fileStream.Close();
                    }

                    DBConnection = new SQLiteAsyncConnection(path);
                    DBConnection.CreateTableAsync<T>().Wait();
                }
                catch (Exception ex)
                {
                    if (ex is UnauthorizedAccessException)
                    {

                    }
                }
            }
        }

        /// <summary>
        /// Create the data table
        /// </summary>
        /// <returns></returns>
        public async Task<CreateTableResult> CreateTableAsync()
        {
            if (DBConnection != null)
            {
                return await DBConnection.CreateTableAsync<T>();
            }

            return CreateTableResult.Migrated;
        }

        /// <summary>
        /// Create a new record entry
        /// </summary>
        /// <param name="entity">Data entity to enter</param>
        /// <param name="user">Current User information</param>
        /// <returns>New entry record if successful</returns>
        public async Task<T> CreateAsync(T entity, IUserRecord user)
        {
            if (entity == null)
            {
                return default(T);
            }

            if (DBConnection == null)
            {
                return default(T);
            }

            entity.CreatedDate = DateTime.UtcNow;
            entity.CreatedByUserId = user.Id;
            entity.Id = 0;
            try
            {
                await DBConnection.InsertAsync(entity);

            }
            catch (SQLiteException e)
            {
                if (e.Message == "Constraint")
                {
                    throw new InvalidConstraintException(e.Message, e.InnerException);
                }
            }            
            var result = entity;

            return result;
        }

        /// <summary>
        /// Update a collection of new entities of type T to the data table.
        /// All entities should be present within the data table
        /// </summary>
        /// <param name="entityList">Entity collection</param>
        /// <param name="user">user making the change</param>
        /// <returns>ID of entities successfully updated or added</returns>
        public async Task<int> UpdateAllAsync(IEnumerable<T> entityList, IUserRecord user)
        {
            var result = 0;
            foreach (var t in entityList)
            {
                if (null != await UpdateAsync(t, user))
                {
                    result++ ;
                }
            }

            return result;
        }

        /// <summary>
        /// Obtain the data record with the given Id
        /// </summary>
        /// <param name="id">Id value to select the record by</param>
        /// <returns>A valid record if found otherwise null</returns>
        public async Task<T> GetById(int id)
        {
            if (DBConnection == null)
            {
                return default(T);
            }

            return await DBConnection.Table<T>().Where(i => i.Id == id).FirstOrDefaultAsync();
        }

        /// <summary>
        /// This function returns all database entries that are not marked deleted or changed
        /// Warning: The data set may be very large
        /// </summary>
        /// <returns>A list of entries</returns>
        public async Task<List<T>> GetAll()
        {
            if (DBConnection != null)
            {
                return await DBConnection.Table<T>().Where(x=>x.ChangedDate==default && x.DeletedDate==default)
                    .ToListAsync();

            }
            return new List<T>();
        }

        /// <inheritdoc />
        public async Task<List<T>> GetAllHistoric() => await DBConnection.Table<T>().ToListAsync();


        /// <summary>
        /// This function is used to update the supplied record entry within the database.
        /// If the supplied record does not have a non-zero value Id field it is assumed to be a
        /// new record to be inserted into the database.
        /// </summary>
        /// <param name="entity">Record to update</param>
        /// <param name="user">User performing the action</param>
        /// <returns></returns>
        public async Task<T> UpdateAsync(T entity, IUserRecord user)
        {
            if (DBConnection == null)
            {
                return default(T);
            }

            if (entity == null)
            {
                return default(T);
            }

            var newRecord = (T) ((entity) as BaseRecord<T>)?.Clone();

            if (null == newRecord)
            {
                return default(T);
            }

            //if Id is zero assume that the record is new and to be added
            if (newRecord.Id == 0)
            {
                if (user != null)
                {
                    newRecord.CreatedByUserId = user.Id;
                }
                newRecord.CreatedDate = DateTime.UtcNow;
                newRecord.Id = await DBConnection.InsertAsync(newRecord);
                return newRecord;
            }

            // Id is not zero and thus a new record should be created linked to the old record.
            var oldRecord = await GetById(newRecord.Id);
            oldRecord.ChangedDate = DateTime.UtcNow;
            if (user != null)
            {
                oldRecord.ChangedByUserId = user.Id;
            }
            try
            {
                var result = await DBConnection.UpdateAsync(oldRecord);

            }
            catch (Exception e)
            {

               Debug.WriteLine($"UpdateAsync {e.Message}");
            }           

            newRecord.PreviousRecordId = oldRecord.Id;
            newRecord.Id = 0;

            return await CreateAsync(newRecord, user);

        }

        /// <inheritdoc />
        public async Task<int> DeleteAsync(T entity)
        {
            if (DBConnection == null)
            {
                return -1;
            }
            return await DBConnection.DeleteAsync(entity);
        }

        /// <inheritdoc />
        public async Task DeleteAll()
        {
            await DBConnection.DropTableAsync<T>();
            await CreateTableAsync();
        }

        /// <inheritdoc />
        public async Task<PagedResult<T>> GetAllPagedResult(int recordId, uint maxResults = 100)
        {
            if (DBConnection == null)
            {
                return null;
            }

            List<T> list;

            if (maxResults == 0)
            {
                list = await GetAll();
            }
            else
            {
                list = await DBConnection.Table<T>().Where(x => (x.Id >= recordId && x.ChangedDate == default && x.DeletedDate == default)).ToListAsync();
                if (list.Count() > maxResults)
                {
                    list = list.GetRange(0, (int) maxResults);
                }
            }

            return new PagedResult<T>(list, list.Count());

        }

        /// <inheritdoc />
        public async Task<IEnumerable<T>> FindAsyncOrdered<TValue>(Expression<Func<T, bool>> predicate = null,
            Expression<Func<T, TValue>> orderBy = null)
        {
            var query = DBConnection.Table<T>();
            if (predicate != null)
            {
                query = query.Where(predicate);
            }

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

            return await query.ToListAsync();
        }

        /// <inheritdoc />
        public async Task<T> FindFirst(Expression<Func<T, bool>> predicate) => await DBConnection.FindAsync(predicate);
    }

我使用的数据类基于:

public interface IDataRecord 
{
    /// <summary>
    /// Identifier for record
    /// </summary>
    int Id { get; set; }

    /// <summary>
    /// Link to previous version of record
    /// </summary>
    int PreviousRecordId { get; set; }

    /// <summary>
    /// User Identity that made the change
    /// </summary>
    int ChangedByUserId { get; set; }

    /// <summary>
    /// Date when the data record was last changed
    /// </summary>
    DateTime ChangedDate { get; set; }

    /// <summary>
    /// Identity of User that deleted the record
    /// </summary>
    int DeletedByUserId { get; set; }

    /// <summary>
    /// Date when the data record was deleted
    /// </summary>
    DateTime DeletedDate { get; set; }

    /// <summary>
    /// Identity of User that created the record
    /// </summary>
    int CreatedByUserId { get; set; }

    /// <summary>
    /// Date when the data record was added
    /// </summary>
    DateTime CreatedDate { get; set; }

    object Clone();
}

显然您不必使用它,但简单地说,对于我的应用程序实现,每种类型的数据记录都存储在其自己的数据文件中(因此每个文件 1 个表),并且它是在构造函数的开头创建的。

  • 使用数据文件路径创建 SQLite db 连接。

  • 表是使用 dbconnection 创建的

编辑

我仔细查看了您的代码。 需要注意的地方是:

  • 您似乎没有创建表。

  • 如果您选择创建 UWP 而不是基础 WPF 项目,则对非应用文件夹的访问受到限制 - 尤其是在发布模式下运行应用时,请注意文件夹访问权限。

【讨论】:

  • 我不得不重做我所做的一切,因为我感到沮丧并重新开始。我仍然无法让我的数据库做任何事情,这次我没有收到任何错误。但它仍然无法正常工作。我正在尝试发布代码供您查看,但我是新手,它几乎不会让我发布任何内容。我可以通过电子邮件将文件发送给您吗?我为要制作的表定义了一个类。我创建了一个引用我的数据库位置的公共部分类。我做了一个按钮,但我不知道我需要使用什么命令。我打开了连接,但我不知道如何插入我创建的类中的值。
  • 我在这里粘贴了一些代码。如果您需要更多,请告诉我。在这一点上,我感到非常困惑。 pastebin.com/rLfVT5BH
  • 嗨,抱歉耽搁了——我从一个工作的 WPF .NET 4.7.2 应用程序中粘贴了一些代码pastebin.com/3JyNT765——它使用最新的 C# 和 SQLite-net v1 的SQLite-net-pcl .7.335 NuGet 包。该应用程序在默认 MainWindow 上只有两个按钮,一个用于触发新用户的创建,另一个用于获取数据库中所有用户的列表。在当前形式下,它同步运行,但我建议您考虑使其异步(使用async Task 类型和SQLiteAsyncConnection)。
猜你喜欢
  • 2021-09-05
  • 2021-07-07
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-27
  • 2023-02-06
  • 1970-01-01
相关资源
最近更新 更多