在C#中处理SQLite-作为命令推进传递字符串操作
我正在我的应用程序中使用SQLite(通过System.Data.SQLite包)。现在,所有插入、查询和其他操作都是通过使用字符串发送命令来完成的,例如:在C#中处理SQLite-作为命令推进传递字符串操作,c#,sqlite,system.data.sqlite,C#,Sqlite,System.data.sqlite,我正在我的应用程序中使用SQLite(通过System.Data.SQLite包)。现在,所有插入、查询和其他操作都是通过使用字符串发送命令来完成的,例如: SQLiteCommand command = new SQLiteCommand(comStr, db); 其中comStr-是一个包含命令的字符串变量 还有其他选项可以替代字符串吗?或者字符串是处理.NET SQL查询时应该使用的正确方法吗 问题是使用字符串会变得相当混乱,例如,我有一些用户可以设置的过滤器。使用字符串
SQLiteCommand command = new SQLiteCommand(comStr, db);
其中comStr-是一个包含命令的字符串变量
还有其他选项可以替代字符串吗?或者字符串是处理.NET 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;
}
公共字符串GetFilterString()
{
字符串fil1=“”;
字符串fil2=“”;
字符串fil3=“”;
字符串fil4=“”;
//按时间过滤
开关(带INTIMEBTNSTATUS)
{
案例与时间。全部:
打破
案例时间:小时:
字符串minusHour=(DateTime.Now-newtimespan(0,1,0,0)).ToString(“yyyy-MM-dd-HH:MM:ss.fff”);
fil1=$“timestamp>=datetime('{minusHour}')”;
打破
时间内的案例。日期:
字符串minusDay=(DateTime.Now-new TimeSpan(1,0,0,0)).ToString(“yyy-MM-dd-HH:MM:ss.fff”);
fil1=$“timestamp>=datetime('{minusDay}')”;
打破
一周内的案例:
字符串minusWeek=(DateTime.Now-newtimespan(7,0,0,0)).ToString(“yyyy-MM-dd-HH:MM:ss.fff”);
fil1=$“timestamp>=datetime('{minusWeek}')”;
打破
}
//扩展过滤
for(int i=0;i
编辑以提供答案中的一些解决方案
本教程向您展示如何正确实现SQLite并使用Linq扩展与数据库表交互。我已经复制了下面的相关部分。一旦打开数据库连接并创建了数据优先表,就可以像使用Linq处理任何IEnumerable一样与该表交互。它还提供了一个将SQL作为字符串传递的选项,但是由于在编译时没有检查该选项,因此您可能会遇到运行时错误
TodoItemDatabase构造函数如下所示:
public TodoItemDatabase(string dbPath)
{
database = new SQLiteAsyncConnection(dbPath);
database.CreateTableAsync<TodoItem>().Wait();
}
公共TodoItemDatabase(字符串dbPath)
{
数据库=新的SQLiteAsyncConnection(dbPath);
database.CreateTableAsync().Wait();
}
这种方法创建一个在应用程序运行时保持打开状态的数据库连接,因此避免了每次执行数据库操作时打开和关闭数据库文件的开销。
TodoItemDatabase类的其余部分包含跨平台运行的SQLite查询。下面显示了示例查询代码(有关语法的更多详细信息,请参阅Using SQLite.NET文章):
public任务GetItemsAsync()
{
返回database.Table().ToListAsync();
}
公共任务GetItemsNotoneAsync()
{
返回database.QueryAsync(“从[TodoItem]中选择*,其中[Done]=0”);
}
公共任务GetItemAsync(int id)
{
返回database.Table().Where(i=>i.ID==ID).FirstOrDefaultAsync();
}
公共任务SaveItemAsync(TodoItem项)
{
如果(item.ID!=0)
{
返回数据库.UpdateAsync(项);
}
否则{
返回数据库.InsertAsync(项);
}
}
公共任务DeleteItemAsync(TodoItem项)
{
返回database.DeleteAsync(项);
}
因为我没有得到满意的答案,所以我将公布我最终做了什么。我认为这可能是一个不错的方法,但可能还有其他更好的方法来实现我所寻找的(在我的数据库上使用LINQ类型语法,而不是使用包含查询的字符串)
另外,我不确定这是否比简单使用查询字符串更快
TL;DR:使用SQLite.CodeFirst+EntityFramework
(另一方面,可以使用LINQ to SQL而不是EntityFramework,但不确定是否也使用CodeFirst方法。在我尝试和测试此方法后将进行更新)
首先,您需要添加以下软件包:
- 实体框架
- System.Data.SQLite(可能还会安装:)
- System.Data.SQLite.Core
- System.Data.SQLite.EF6
- System.Data.SQLite.Linq
- SQLite.CodeFirst
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);
}
<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>
<connectionStrings>
<add name="YourModel" connectionString="Data Source=|DataDirectory|\NameOfYourDBFile.sqlite" providerName="System.Data.SQLite" />
</connectionStrings>
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.
}
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);
}
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;
}