代码之家  ›  专栏  ›  技术社区  ›  Maverick Meerkat

在C#中处理SQLite-作为命令推进传递字符串操作

  •  1
  • Maverick Meerkat  · 技术社区  · 7 年前

            SQLiteCommand command = new SQLiteCommand(comStr, db);
    

    有没有其他选项可以代替字符串? 或者字符串是处理来自的SQL查询时应该使用的正确方法。网络?

        public string GetFilterString()
        {
            string fil1 = "";
            string fil2 = "";
            string fil3 = "";
            string fil4 = "";
    
            // filter by time
            switch (WithinTimeBtnStatus)
            {
                case WithinTime.All:
                    break;
                case WithinTime.Hour:
                    string minusHour = (DateTime.Now - new TimeSpan(0, 1, 0, 0)).ToString("yyyy-MM-dd HH:mm:ss.fff");
                    fil1 = $" timestamp >= datetime('{minusHour}')";
                    break;
                case WithinTime.Day:
                    string minusDay = (DateTime.Now - new TimeSpan(1, 0, 0, 0)).ToString("yyyy-MM-dd HH:mm:ss.fff");
                    fil1 = $" timestamp >= datetime('{minusDay}')";
                    break;
                case WithinTime.Week:
                    string minusWeek = (DateTime.Now - new TimeSpan(7, 0, 0, 0)).ToString("yyyy-MM-dd HH:mm:ss.fff");
                    fil1 = $" timestamp >= datetime('{minusWeek}')";
                    break;
            }
    
            // filter by extension
            for (int i = 0; i < FilteredExt.Count; i++)
            {
                fil2 += " ext != '" + FilteredExt[i] + "'";
                if (i < FilteredExt.Count - 1)
                    fil2 += " and";
            }
    
            // filter by process
            if (_processFilterSelected.ToLower() != "all" && _processFilterSelected != "")
            {
                fil3 = $" proc == '{_processFilterSelected}'";
            }
    
            // filter by File Operation
            if (_FileOperationFilterSelected.ToLower() != "all" && _FileOperationFilterSelected != "")
            {
                FileOperation fo = Converters.StringToFileOperation(_FileOperationFilterSelected);
                switch (fo)
                {
                    case FileOperation.Deleted:
                        fil4 = " oper == 'DELETED'";
                        break;
                    case FileOperation.Renamed:
                        fil4 = " oper == 'RENAMED'";
                        break;
                    case FileOperation.Modified:
                        fil4 = " oper == 'MODIFIED'";
                        break;
                }
            }
    
    
            string fil = "";
            var tmp = new[] { fil1, fil2, fil3, fil4 };
            foreach (var t in tmp)
            {
                if (t != "")
                {
                    fil += " and" + t;
                }
            }
    
            return fil;
        }
    
    2 回复  |  直到 7 年前
        1
  •  1
  •   Maverick Meerkat    7 年前

    由于我没有得到满意的答案,我将张贴我最终做了什么。我认为这可能是一种不错的方式,但可能还有其他更好的方式来实现我所寻求的(在我的数据库中使用LINQ类型语法,而不是使用包含查询的字符串)。

    TL;DR:使用SQLite。CodeFirst+EntityFramework。


    首先,您需要添加以下软件包:

    • 系统数据SQLite(可能也会安装:)
    • 系统数据SQLite。果心
    • 系统数据SQLite。林克

    最后,如果你从代码开始(就像我一样),你还需要

    • SQLite。代码优先

    接下来要做的是在应用程序中设置连接字符串。配置。

    (另一方面,在指定提供程序时似乎有很多错误,卸载和重新安装上述软件包似乎可以修复这些错误。我不太确定删除和添加以及不变名称背后的逻辑-如果你关心我写的内容,那么是这样的:

    <system.data>
       <DbProviderFactories>
          <remove invariant="System.Data.SQLite.EF6" />
          <add name="SQLite Data Provider (Entity Framework 6)" invariant="System.Data.SQLite.EF6" description=".NET Framework Data Provider for SQLite (Entity Framework 6)" type="System.Data.SQLite.EF6.SQLiteProviderFactory, System.Data.SQLite.EF6" />
          <remove invariant="System.Data.SQLite" />
          <add name="SQLite Data Provider" invariant="System.Data.SQLite" description=".NET Framework Data Provider for SQLite" type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite" />
       </DbProviderFactories>
    </system.data>
    
    <entityFramework>
      <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
        <providers>
          <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
          <provider invariantName="System.Data.SQLite.EF6" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6" />
          <provider invariantName="System.Data.SQLite" type="System.Data.SQLite.EF6.SQLiteProviderServices, System.Data.SQLite.EF6"/>
         </providers>
      </entityFramework>
    

    )

    连接字符串应该指定一个名称,以及至少一个DB文件所在的路径。您还可以使用稍后在代码中定义的相对路径(通过使用| DataDirectory |语法):

    <connectionStrings>
      <add name="YourModel" connectionString="Data Source=|DataDirectory|\NameOfYourDBFile.sqlite" providerName="System.Data.SQLite" />
    </connectionStrings>
    

    下一步,如果您先编写代码,则创建一个新类作为您的模型,这基本上是使用SQLite。CodeFirst软件包:

    class YourModel : DbContext
    {
        // Your context has been configured to use a 'YourModel' connection string from your application's 
        // configuration file (App.config or Web.config). By default, this connection string targets the 
        // 'YourProject.YourModel' database on your LocalDb instance. 
        // 
        // If you wish to target a different database and/or database provider, modify the 'YourModel' 
        // connection string in the application configuration file.
        public YourModel()
            : base("name=YourModel")
        {
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            var sqliteConnectionInitializer = new SqliteCreateDatabaseIfNotExists<YourModel>(modelBuilder);
            Database.SetInitializer(sqliteConnectionInitializer);
            Database.SetInitializer(new SqliteDropCreateDatabaseWhenModelChanges<YourModel>(modelBuilder));
        }
    
        // Add a DbSet for each entity type that you want to include in your model. For more information 
        // on configuring and using a Code First model, see http://go.microsoft.com/fwlink/?LinkId=390109.
    
        public virtual DbSet<YourTableClass> YourTable { get; set; }
    }
    
    [Table("YourTable")]
    public class YourTableClass
    {
        [Key]
        public string Id { get; set; }
        [Required]
        public FileOperation Oper { get; set; }
        [Required, Index]
        public OperationState State { get; set; }
        [Index]
        public string Proc { get; set; }
        [Required]
        public string Src { get; set; }
        public DateTime Timestamp { get; set; }
        // etc.
    }
    

    你可以了解更多 here

    AppDomain.CurrentDomain.SetData("DataDirectory", @"the\path\you\desire");
    

    现在你可以用它了。基本语法非常简单,您只需使用:

    using (var context = new YourModel())
    {
         // some query
    }
    

    选择

    using (var context = new YourModel())
    {
         var t = context.YourTable
           .Where(e => e.State == OperationState.BackedUp)
           .Select(e => e.Proc)
           .Distinct()
     }
    

    如果你想的话 插入

    using (var context = new YourModel())
    {
        var e = context.YourTable.Create();
        e.Id = guid;
        // ...etc
        e.Timestamp = timestamp;
        context.YourTable.Add(e);
        context.SaveChanges();
    }
    

    如果仍要使用字符串查询:

    using (var context = new YourModel())
    {
        context.Database.ExecuteSqlCommand(comString);
    }
    

    • 如果您更改数据库中的某些内容,您必须致电 Context.SaveChange() 最后(ExecuteSqlCommand不需要这个)
    • 删除可以通过RemoveRange+SaveChange()或仍然使用查询字符串来完成。

        public static IQueryable<YourTable> GetFilteredQueryable(IQueryable<YourTable> yourTable)
        {
            // filter by time
            switch (RestoreLogic.WithinTimeBtnStatus)
            {
                case WithinTime.All:
                    break;
                case WithinTime.Hour:
                    DateTime offsetHour = DateTime.Now.Add(new TimeSpan(-1, 0, 0));
                    yourTable = yourTable.Where(e => e.Timestamp >= offsetHour);
                    break;
               // etc.
            }
    
            // filter by extension
            foreach (var i in FilteredExt)
            {
                yourTable = yourTable.Where(e => e.Ext != i);
            }
    
            // etc.
    
            return yourTable;
        }
    
        2
  •  -2
  •   Joagwa    7 年前

    编辑以提供答案中的一些解决方案。

    本教程向您展示了如何正确实现SQLite并使用Linq扩展与数据库表交互。我已经复制了下面的相关部分。打开数据库连接并创建数据优先表后,就可以像使用Linq处理任何IEnumerable一样与该表交互。它还提供了一个将SQL作为字符串传递的选项,但是由于在编译时未对此进行检查,因此存在运行时错误的风险。

    https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/databases/

    public TodoItemDatabase(string dbPath)
    {
      database = new SQLiteAsyncConnection(dbPath);
      database.CreateTableAsync<TodoItem>().Wait();
    }
    

    这种方法创建了一个在应用程序运行时保持打开的数据库连接,因此避免了每次执行数据库操作时打开和关闭数据库文件的费用。 TodoItemDatabase类的其余部分包含跨平台运行的SQLite查询。示例查询代码如下所示(有关语法的更多详细信息,请参阅Using SQLite.NET文章):

    public Task<List<TodoItem>> GetItemsAsync()
    {
      return database.Table<TodoItem>().ToListAsync();
    }
    
    public Task<List<TodoItem>> GetItemsNotDoneAsync()
    {
      return database.QueryAsync<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");
    }
    
    public Task<TodoItem> GetItemAsync(int id)
    {
      return database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync();
    }
    
    public Task<int> SaveItemAsync(TodoItem item)
    {
      if (item.ID != 0)
      {
        return database.UpdateAsync(item);
      }
      else {
        return database.InsertAsync(item);
      }
    }
    
    public Task<int> DeleteItemAsync(TodoItem item)
    {
      return database.DeleteAsync(item);
    }