Is it possible to check if an SQLite table exists. - sqlite

I have the following code:
dbcon = DependencyService.Get<ISQLite>().GetConnection();
// create the tables
dbcon.CreateTable<Category>();
dbcon.CreateTable<Settings>();
var settings = dbcon.Table<Settings>().ToList();
if (settings.Count <= 0)
{
var noa = new Settings { Setting = "NumberOfAnswers", Value = 5 };
var cfs = new Settings { Setting = "CardFrontSide", Value = 0 };
dbcon.Insert(noa);
dbcon.Insert(cfs);
}
var categories = dbcon.Table<Category>().ToList();
if (categories.Count <= 0)
{
InsertCategory();
}
From what I can see the application is using SQLite-net
What I would like to know is if there is a way I can check to see if a table exists rather than do this which is to try and create it anyway and then try to check if it has rows in it.

This query will return the list of tables in the database
SELECT * FROM sqlite_master WHERE type = 'table';
You can filter it down to a single row for an "exists" check.
SELECT * FROM sqlite_master WHERE type = 'table' AND tbl_name = 'xyz';

You can do something like this:
public static bool TableExists<T> (SQLiteConnection connection)
{
const string cmdText = "SELECT name FROM sqlite_master WHERE type='table' AND name=?";
var cmd = connection.CreateCommand (cmdText, typeof(T).Name);
return cmd.ExecuteScalar<string> () != null;
}
Source

You can use the below codes
public bool IsTableExists(string tableName)
{
try
{
var tableInfo = database.GetConnection().GetTableInfo(tableName);
if(tableInfo.Count > 0)
{
return true;
}
else
{
return false;
}
}
catch
{
return false;
}
}
public SQLiteAsyncConnection database;
public ClientDatabase(string dbPath)
{
database = new SQLiteAsyncConnection(dbPath);
}

Related

Use stored procedure for search method

I started with ASP.Net Core 2.0, I'm trying to rewrite a method GetAll by search use stored procedure. Here is method search:
public async Task<List<DepartmentTypeDto>> SearchDepartmentType()
{
EnsureConnectionOpen();
using (var command = CreateCommand("CM_DEPT_GROUP_Search", CommandType.StoredProcedure))
{
using (var dataReader = await command.ExecuteReaderAsync())
{
List<DepartmentTypeDto> result = new List<DepartmentTypeDto>();
while (dataReader.Read())
{
DepartmentTypeDto departmentTypeDto = new DepartmentTypeDto
{
GROUP_ID = dataReader["GROUP_ID"].ToString(),
GROUP_CODE = dataReader["GROUP_CODE"].ToString(),
GROUP_NAME = dataReader["GROUP_NAME"].ToString(),
NOTES = dataReader["NOTES"].ToString(),
RECORD_STATUS = dataReader["RECORD_STATUS"].ToString(),
MAKER_ID = dataReader["MAKER_ID"].ToString(),
CREATE_DT = Convert.ToDateTime(dataReader["CREATE_DT"]),
AUTH_STATUS = dataReader["AUTH_STATUS"].ToString(),
CHECKER_ID = dataReader["CHECKER_ID"].ToString(),
APPROVE_DT = Convert.ToDateTime(dataReader["APPROVE_DT"]),
AUTH_STATUS_NAME = dataReader["AUTH_STATUS_NAME"].ToString(),
RECORD_STATUS_NAME = dataReader["RECORD_STATUS_NAME"].ToString()
};
}
return result;
}
}
}
Here is the service:
public async Task<PagedResultDto<GetDepartmentTypeForView>> GetAll(GetAllDepartmentTypesInput input)
{
var filteredDepartmentTypes = _departmentTypeRepository.SearchDepartmentType();
var query = (from o in filteredDepartmentTypes
select new GetDepartmentTypeForView() { DepartmentType = ObjectMapper.Map<DepartmentTypeDto>(o) });
var totalCount = await query.CountAsync();
var departmentTypes = await query
.OrderBy(input.Sorting ?? "departmentType.id asc")
.PageBy(input)
.ToListAsync();
return new PagedResultDto<GetDepartmentTypeForView>(totalCount, departmentTypes);
}
But I get an error:
Task<List<DepartmentTypeDto>> does not contain a definition for Select
Does anyone know what I should do? I work on Asp.Net Zero.
I changed my search method
public IQueryable<DepartmentTypeView> SearchDepartmentType(GetAllDepartmentTypesInput input, int top)
{
try
{
var GROUP_FILTER = input.Filter;
var GROUP_CODE = input.GROUP_CODEFilter;
var GROUP_NAME = input.GROUP_NAMEFilter;
var AUTH_STATUS = input.AUTH_STATUSFilter;
var result = Context.Query<DepartmentTypeView>().FromSql($"EXEC CM_DEPT_GROUP_Search #p_GROUP_FILTER = {GROUP_FILTER}, #p_GROUP_CODE={GROUP_CODE}, #p_GROUP_NAME={GROUP_NAME}, #p_AUTH_STATUS={AUTH_STATUS}, #p_TOP={top}");
return result;
}
catch
{
return null;
}
}
and in the service, I call that function
var filteredDepartmentTypes = _departmentTypeRepository.SearchDepartmentType(input,100);
I also create new class to keep the result and don't forget to map that class with DTO class
configuration.CreateMap<DepartmentTypeView, DepartmentTypeDto>();
It works for me.

Retrieve an Entity value to add to return parameter

I have this method:
private List < ReportParameter > ParametrosReporte() {
List < ReportParameter > Parametros = new List < ReportParameter > ();
try {
int ? int_Ejercicio = this.radcmbEjercicio.SelectedItem == null ? 0 : this.radcmbEjercicio.SelectedValue.ToInt();
int ? int_Periodo = this.radcmbPeriodo.SelectedItem == null ? 0 : this.radcmbPeriodo.SelectedValue.ToInt();
int ? int_BSC = this.radcmbBSC.SelectedItem == null ? 0 : this.radcmbBSC.SelectedValue.ToInt();
Parametros.Add(Reportes.ParametrosReporte("pe_Ejercicio", int_Ejercicio.ToString()));
Parametros.Add(Reportes.ParametrosReporte("pe_Mes", int_Periodo.ToString()));
Parametros.Add(Reportes.ParametrosReporte("pe_BSC", int_BSC.ToString()));
catBSC _catBSC = new catBSC() {
mdUsuarioCaptura = new Entidades.Usuario() {
UsuarioID = ((Usuario) Session["User"]).UsuarioID,
}
};
Parametros.Add(Reportes.ParametrosReporte("pe_Usuario", UsuarioID ));
return Parametros;
} catch (Exception ex) {
throw new System.ArgumentException("Error en ParametrosReporte", ex);
}
}
As you can see I have logic to retrieve user who is logged in as:
catBSC _catBSC = new catBSC() {
mdUsuarioCaptura = new Entidades.Usuario() {
UsuarioID = ((Usuario) Session["User"]).UsuarioID,
}
};
but before retrieve it, I want to call it into Parametros.Add like:
Parametros.Add(Reportes.ParametrosReporte("pe_Usuario", UsuarioID ));
But I canĀ“t because UsuarioID is out of scope and it throws me
UsuarioID does not exist in the current context
How can I call it and attach to my Parametros.Add?
You can just create a local variable above your creation of catBSC and then use that in both locations:
var usuarioID = ((Usuario) Session["User"]).UsuarioID
catBSC _catBSC = new catBSC() {
mdUsuarioCaptura = new Entidades.Usuario() {
UsuarioID = usuarioID
}
};
Parametros.Add(Reportes.ParametrosReporte("pe_Usuario", usuarioID));
You can replace var with the actual type, but I didn't want to make an assumption about what this was in your scenario.

Can I generate SQL scripts with ServiceStack OrmLite?

Is it possible to generate SQL scripts using OrmLite without executing it against a database? I would like to load a list of DTOs from a live SqlServer database and output a script to DELETE and INSERT each record.
The provided mini profiler supports logging, but looks like it needs to wrap a real database connection.
This is trivial now that OrmLite extension methods are now mockable by providing your own OrmLiteResultsFilter.
E.g. this ResultsFilter below records every sql statement executed and inherts the behavior from OrmLiteResultsFilter to return empty results:
public class CaptureSqlFilter : OrmLiteResultsFilter
{
public CaptureSqlFilter()
{
SqlCommandFilter = CaptureSqlCommand;
SqlCommandHistory = new List<SqlCommandDetails>();
}
private void CaptureSqlCommand(IDbCommand command)
{
SqlCommandHistory.Add(new SqlCommandDetails(command));
}
public List<SqlCommandDetails> SqlCommandHistory { get; set; }
public List<string> SqlStatements
{
get { return SqlCommandHistory.Map(x => x.Sql); }
}
}
You can wrap this in an using scope to capture each SQL statement without executing them, e.g:
using (var captured = new CaptureSqlFilter())
using (var db = OpenDbConnection())
{
db.CreateTable<Person>();
db.Select<Person>(x => x.Age > 40);
db.Single<Person>(x => x.Age == 42);
db.Count<Person>(x => x.Age < 50);
db.Insert(new Person { Id = 7, FirstName = "Amy", LastName = "Winehouse" });
db.Update(new Person { Id = 1, FirstName = "Jimi", LastName = "Hendrix" });
db.Delete<Person>(new { FirstName = "Jimi", Age = 27 });
db.SqlColumn<string>("SELECT LastName FROM Person WHERE Age < #age",
new { age = 50 });
db.SqlList<Person>("exec sp_name #firstName, #age",
new { firstName = "aName", age = 1 });
db.ExecuteNonQuery("UPDATE Person SET LastName={0} WHERE Id={1}"
.SqlFmt("WaterHouse", 7));
var sql = string.Join(";\n\n", captured.SqlStatements.ToArray());
sql.Print();
}
Which prints out:
CREATE TABLE "Person"
(
"Id" INTEGER PRIMARY KEY,
"FirstName" VARCHAR(8000) NULL,
"LastName" VARCHAR(8000) NULL,
"Age" INTEGER NOT NULL
);
;
SELECT "Id", "FirstName", "LastName", "Age"
FROM "Person"
WHERE ("Age" > 40);
SELECT "Id", "FirstName", "LastName", "Age"
FROM "Person"
WHERE ("Age" = 42)
LIMIT 1;
SELECT COUNT(*) FROM "Person" WHERE ("Age" < 50);
INSERT INTO "Person" ("Id","FirstName","LastName","Age") VALUES (#Id,#FirstName,#LastName,#Age);
UPDATE "Person" SET "FirstName"=#FirstName, "LastName"=#LastName, "Age"=#Age WHERE "Id"=#Id;
DELETE FROM "Person" WHERE "FirstName"=#FirstName AND "Age"=#Age;
SELECT LastName FROM Person WHERE Age < #age;
exec sp_name #firstName, #age;
UPDATE Person SET LastName='WaterHouse' WHERE Id=7
More examples available in CaptureSqlFilterTests.cs
As CaptureSqlFilter is useful I've just added it to OrmLite in this commit which will be in the next v4.0.20 that's now available on MyGet.
Using the DialectProvider directly seems to work well enough for what I need. ToInsertRowStatement takes a IDbCommand paramater, but does not use it so null works.
OrmLiteConfig.DialectProvider = SqlServerOrmLiteDialectProvider.Instance;
var dto = new PersonDTO { Id = Guid.NewGuid(), Name = "Carl" };
var deleteText = SqlServerOrmLiteDialectProvider.Instance.ToDeleteRowStatement(dto);
var insertText = SqlServerOrmLiteDialectProvider.Instance.ToInsertRowStatement((IDbCommand)null, dto);
Is there a better alternative?
I use this to capture the statement and keep running the sentense.
public class CustomOrmLiteExecFilter : OrmLiteExecFilter
{
public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter)
{
var holdProvider = OrmLiteConfig.DialectProvider;
var dbCmd = CreateCommand(dbConn);
try
{
var ret = filter(dbCmd);
var pureSQL = holdProvider.MergeParamsIntoSql(dbCmd.CommandText, dbCmd.Parameters.OfType<IDbDataParameter>());
//log or save the SQL Statement
return ret;
}
finally
{
if (OrmLiteConfig.DialectProvider != holdProvider)
OrmLiteConfig.DialectProvider = holdProvider;
}
}
}
and the usage:
OrmLiteConfig.ExecFilter = new CustomOrmLiteExecFilter();
hope this can help you!

Asp.Net MVC3, Update query in Linq

I'd like to know how to run this query in Linq way.
UPDATE orders SET shipDate = '6/15/2012' WHERE orderId IN ('123123','4986948','23947439')
My Codes,
[HttpGet]
public void test()
{
EFOrdersRepository ordersRepository = new EFOrdersRepository();
var query = ordersRepository.Orders;
// How to run this query in LINQ
// Query : UPDATE orders SET shipDate = '6/15/2012' WHERE orderId IN ('123123','4986948','23947439')
}
EFOrdersRepository.cs
public class EFOrdersRepository
{
private EFMysqlContext context = new EFMysqlContext();
public IQueryable<Order> Orders
{
get { return context.orders; }
}
}
EFMysqlContext.cs
class EFMysqlContext : DbContext
{
public DbSet<Order> orders { get; set; }
}
Actually it's pretty easy check the following code
EFOrdersRepository db = new EFOrdersRepository();
int[] ids= new string[] { "123123", "4986948", "23947439"};
//this linq give's the orders with the numbers
List<Order> orders = db.Order().ToList()
.Where( x => ids.Contains(x.orderId.Contains));
foreach(var order in orders)
{
order.ShipDate = '06/15/2012';
db.Entry(usuario).State = EntityState.Modified;
}
db.SaveChanges();
Something like this should work (warning Pseudo code ahead!!)
EDIT I like using the Jorge's method of retrieving the orders better (using contains), but leaving this here as another alternative. The statements below the code sample still hold true however.
[HttpGet]
public void test()
{
EFOrdersRepository ordersRepository = new EFOrdersRepository();
var query = ordersRepository.Orders.Where(x=>x.orderId == '123123' ||
x.orderId == '4986948' || x.orderId = '23947439').ToList();
foreach(var order in query){
var localOrder = order;
order.ShipDate = '06/15/2012';
}
ordersRepository.SaveChanges();
}
Basically, LINQ does not do 'bulk updates' well. You either have to fetch and loop through your orders or write a stored procedure that can take an array of ids and bulk update them that way. If you are only doing a few at a time, the above will work ok. If you have tons of orders that need to be updated, the ORM probably will not be the best choice. I look forward to see if anyone else has a better approach.
Disclaimer: the var localOrder = order line is to ensure that there are no modified closure issues. Also, ReSharper and other tools may have a less verbose way of writing the above.
Note: You need to call SaveChanges from your DBContext at the end
Short answer:
var f = new[] { 123123, 4986948, 23947439 };
var matchingOrders = orders.Where(x => f.Contains(x.ID)).ToList();
matchingOrders.ForEach(x => x.ShipDate = newDate);
Complete test:
// new date value
var newDate = new DateTime(2012, 6, 15);
// id's
var f = new[] { 123123, 4986948, 23947439 };
// simpulating the orders from the db
var orders = Builder<Order2>.CreateListOfSize(10).Build().ToList();
orders.Add(new Order2 { ID = 123123 });
orders.Add(new Order2 { ID = 4986948 });
orders.Add(new Order2 { ID = 23947439 });
// selecting only the matching orders
var matchingOrders = orders.Where(x => f.Contains(x.ID)).ToList();
matchingOrders.ForEach(x => Console.WriteLine("ID: " + x.ID + " Date: " + x.ShipDate.ToShortDateString()));
// setting the new value to all the results
matchingOrders.ForEach(x => x.ShipDate = newDate);
matchingOrders.ForEach(x => Console.WriteLine("ID: " + x.ID + " Date: " + x.ShipDate.ToShortDateString()));
Output:
ID: 123123 Date: 1/1/0001
ID: 4986948 Date: 1/1/0001
ID: 23947439 Date: 1/1/0001
ID: 123123 Date: 6/15/2012
ID: 4986948 Date: 6/15/2012
ID: 23947439 Date: 6/15/2012
In ORMs, You have to fetch the record first make the change to the record then save it back. To do that, I will add an UpdateOrder method to my Repositary like this
public bool UpdateOrder(Order order)
{
int result=false;
int n=0;
context.Orders.Attach(order);
context.Entry(order).State=EntityState.Modified;
try
{
n=context.SaveChanges();
result=true;
}
catch (DbUpdateConcurrencyException ex)
{
ex.Entries.Single().Reload();
n= context.SaveChanges();
result= true;
}
catch (Exception ex2)
{
//log error or propogate to parent
}
return result;
}
And i will call it from my Action method like this
int orderId=123232;
var orders=ordersRepository.Orders.Where(x=> x.orderId.Contains(orderId)).ToList();
if(orders!=null)
{
foreach(var order in orders)
{
order.ShipDate=DateTime.Parse('12/12/2012);
var result= ordersRepository.UpdateOrder();
}
}
In this Approach, if you have to update many number of records, you are executing thatn many number of update statement to the database. In this purticular case, i would like to execute the Raw SQL statement with only one query using the Database.SqlQuery method
string yourQry="UPDATE orders SET shipDate = '6/15/2012'
WHERE orderId IN ('123123','4986948','23947439')";
var reslt=context.Database.SqlQuery<int>(yourQry);

How to create auto generate id for ListOf rows returned

I am accessing list of data as shown below.
var result = (from Pages in PagesList.Items.OfType<SPListItem>()
select new ListImages
{
desc = Convert.ToString(Pages["Description"])
}).ToList();
What I want is to auto generate customized increamental id for the no of rows generated.
ex, slide-img-1, slide-img-2 etc.
public class ListImages
{
string _desc;
string _id;
public string id
{
get
{
if (_id != null)
return _id;
else
return string.Empty;
}
set { _id = value; }
}
public string desc
{
get
{
if (_desc != null)
return _desc;
else
return string.Empty;
}
set { _desc = value; }
}
}
Thanks,
Ashish
I don't know if it can be achieved with the Linq specific syntax, but writing your query like this, you could use the .Select() method that provides an index:
var result = PagesList.Items.OfType<SPListItem>()
.Select((page, index) => new ListImages
{
desc = Convert.ToString(page["Description"]),
id = String.Concat("slide-img-", index + 1)
})
.ToList();

Resources