Xamarin Forms delete from sqlite database - c#

I have a class Announcement, and I have a list of id, I am using the nuget package: sqlite-net-pcl.
How can I delete an announcement from my Announcement table if I have it id. I am trynig to use linq like: await connection.DeleteAsync(announcement).Where(...)
but I can't use Where with the DeleteAsync, so I tried
var query = connection.Table<Announcement>().Where(announcement=>announcement.AnnouncementId == announcementId)
it gives me this erro :System.NotSupportedException: Cannot delete AsyncTableQuery`1: it has no PK

I think you are looking for something like this:
public static int Delete(string url)
{
using (var databaseManager = DatabaseManager.Instance)
{
lock (databaseManager)
{
return databaseManager.Database.Table<File>().Delete(x => x.Url == url);
}
}
}
This is using SQLite;
https://developer.xamarin.com/guides/android/data-and-cloud-services/data-access/part-3-using-sqlite-orm/

I have never used the nuget in question but I have had a quick look on the source and it would appear that TableQuery has a sync method called Delete that returns an integer.
The code you have included above is returning an object of type TableQuery<Announcement>. The class TableQuery contains the following definition:
public int Delete(Expression<Func<T, bool>> predExpr)
{
if (predExpr.NodeType == ExpressionType.Lambda) {
var lambda = (LambdaExpression)predExpr;
var pred = lambda.Body;
var args = new List<object> ();
var w = CompileExpr (pred, args);
var cmdText = "delete from \"" + Table.TableName + "\"";
cmdText += " where " + w.CommandText;
var command = Connection.CreateCommand (cmdText, args.ToArray ());
int result = command.ExecuteNonQuery();
return result;
} else {
throw new NotSupportedException ("Must be a predicate");
}
}
It would seem that you should just use the following:
connection.Table<Announcement>().Delete(announcement=>announcement.AnnouncementId == announcementId)
This code is completely untested and is from reviewing the source code of the nuget package on Github (https://github.com/praeclarum/sqlite-net/blob/master/src/SQLite.cs).

Have your ID Property the Primary Key Attribute ?
[PrimaryKey,AutoIncrement]
public int Id { get; set; }

Related

The procedure "SP_name" has no parameter named "#typ_table" in dapper.net

What I Want.
If user enter duplicated value, then i want to delete that duplicate value and install the new one. I don't want to use update query because of some requirement.
Code:
Web API
public CoCApiResponse CreateVersion(CreateVersion versionObj)
{
var taskForDelete = Task.Run(() =>
versionRepository.DeleteVersions(objVersionCollection));
taskForDelete.Wait();
versionRepository.CreateVersion(versionObj.version, lstVersion).Result;
}
Repository:
public async Task<Version> DeleteVersions(CoCBaseCollection<Version> Versions)
{
List<Version> versionList = new List<Version>();
foreach (var objVersion in Versions)
{
Version version = new Version()
{
Id = objVersion.Id,
VersionName = objVersion.VersionName,
StructureWeek = objVersion.StructureWeek,
IsWLTP = objVersion.IsWLTP,
VersionStatusTypeId = objVersion.VersionStatusTypeId,
CreatedDateTime = System.DateTime.Now,
LastUpdatedDateTime = System.DateTime.Now
};
versionList.Add(version);
}
int retval = 0;
DataTable dtVersions = TableConversion.EnitiesToDataTable<Version>(versionList);
pars = new DynamicParameters();
pars.Add("#VersionTableForDelete", dtVersions.AsTableValuedParameter("dbo.VersionTable"));
pars.Add("#Retval", retval, DbType.Int32, ParameterDirection.Output);
string DeleteVersionSP = "dbo.DeleteVersions";
return await ExecSproc<Version>(DeleteVersionSP, pars, new Version()).ConfigureAwait(false);
}
public async Task<Version> CreateVersion(Version version, List<Version> versions)
{
int retval = 0;
DataTable dtVersions = TableConversion.EnitiesToDataTable<Version>(versions);
pars.Add("#refVersionTable", dtVersions.AsTableValuedParameter("dbo.VersionTable"));
pars.Add("#Retval", retval, DbType.Int32, ParameterDirection.Output);
string CreateVersionSP = "dbo.SPCreateVersion";
return await ExecSproc<Version>(CreateVersionSP, pars, version).ConfigureAwait(false);
}
Problem
I am getting this below error, while I am running the Delete and Create method
The procedure "SPCreateVersion" has no parameter named "#VersionTableForDelete".
What I have tried.
I have checked with my Store Procedure and it's working fine and also searched more than 2 hour from google But I am unable to resolve it. Because no one given the exact solution for dapper.net
Finally, What I found :
Yeah! It is working while doing delete and insert separately
public CoCApiResponse CreateVersion(CreateVersion versionObj)
{
versionRepository.CreateVersion(versionObj.version).Result;// working
}
//
public CoCApiResponse CreateVersion(CreateVersion versionObj)
{
var taskForDelete = Task.Run(() =>
versionRepository.DeleteVersions(versionObj));//working
taskForDelete.Wait();
}
But it is throwing the error while inserting, if we are doing both delete and insert.
public CoCApiResponse CreateVersion(CreateVersion versionObj)
{
var taskForDelete = Task.Run(() =>
versionRepository.DeleteVersions(versionObj));//working
taskForDelete.Wait();
versionRepository.CreateVersion(versionObj.version).Result;// Not Working and throwing an error
}
What I Guess
this error may be related with asyn/sync callback problem. But I don't have any idea to resolve this.
How can we resolve this?
This issue has been resolved while I clear the parameters before adding a new parameters in CreateVersion Store Procedure
like
pars = new DynamicParameters();
Full code is
public async Task<Version> CreateVersion(Version version, List<Version> versions)
{
int retval = 0;
DataTable dtVersions = TableConversion.EnitiesToDataTable<Version>(versions);
pars = new DynamicParameters();// this line resolved the issue
pars.Add("#refVersionTable", dtVersions.AsTableValuedParameter("dbo.VersionTable"));
pars.Add("#Retval", retval, DbType.Int32, ParameterDirection.Output);
string CreateVersionSP = "dbo.SPCreateVersion";
return await ExecSproc<Version>(CreateVersionSP, pars, version).ConfigureAwait(false);
}

Cannot assign a void to an implicitly-typed local variable using Entity Framework 6

I am using a WCF refrence to call the last row from my Quote table. Now I wrote this method in my WCF application to get the last row, but I do not know it it works or not(I am trying to test it):
public void GetLastQuote()
{
using (TruckDb db = new TruckDb())
{
var quote = (from qData in db.Quotes
where qData.Id == qData.RepresetativeId
orderby qData.Id descending
select qData).First();
}
}
In my WPF application I am using the WCF reference and calling on the GetLastQuoteAsync() method, but it is giving me the following error:
Cannot assign void to an implicitly-typed local variable
And here is the method in my WPF application where I am trying to call the GetLastQuoteAsync() reference.
private async void wListOfBills_Loaded(object sender, RoutedEventArgs e)
{
using (TruckServiceClient client = new TruckServiceClient())
{
var quote = await client.GetLastQuoteAsync(); // -> This is where the error lies.
var bills = await client.GetListOfBillsAsync(quote.Item.Id);
if (bills == null)
{
dgFloor.IsEnabled = true;
return;
}
dgFloor.ItemsSource = bills.Select(x => new ListOfBillsView
{
Code = x.StockCode,
Group = x.GroupName,
Description = x.StockDescription,
Qty = x.Quantity,
Length = x.Length,
Width = x.Width,
Weight = x.Weight,
Price_m = x.PricePerMeter,
Cost = x.Cost,
Section = x.TruckSection.ToString()
}).ToList();
}
}
I have seen some people with the same question, but I do not fully understand how to implement the solutions in my own problem. If anyone could help, I would appreciate it allot! :)
You want to call what your query is returning, but the method wrapping around that query is returning nothing, because its type is void.
I assume you want to return an object of type Quote, so you need to change your method to this:
//change from void to Quote
public Quote GetLastQuote()
{
using (TruckDb db = new TruckDb())
{
var quote = (from qData in db.Quotes
where qData.Id == qData.RepresetativeId
orderby qData.Id descending
select qData).First();
//new
return quote;
}
}
Also GetLastQuote() is not the same as GetLastQuoteAsync() Have you posted the wrong method, which would throw the same error?
If there is also async version of this method it should probably look similar to this:
public async Task<Quote> GetLastQuote()
{
using (TruckDb db = new TruckDb())
{
var quote = (from qData in db.Quotes
where qData.Id == qData.RepresetativeId
orderby qData.Id descending
select qData).FirstAsync(); /*Note async method here*/
//new
return await quote;
}
}

Generate lambda expression from string

I have a need to store lambda expressions in a database and execute them dynamically. The following snippet works well as is,
float result = dataRowArray.AsEnumerable().Sum(r => r.Field<float>("ColumnA") * r.Field<float>("ColumnB"));
but I'd like to store the following part in a string...
r => r.Field<float>("ColumnA") * r.Field<float>("ColumnB")
... and inject it dynamically as in:
float result = MySession.Current.dr.AsEnumerable().Sum(storedLambdaString);
I've done a ton of Googling but I'm coming up short. Any suggestions?
I suggest store the query in the database and execute using LINQ like below.
using (eEntities db = new eEntities())
{
string query = "select name,age,salary from employees"
var employees = db.Database.SqlQuery<Employee>(query).
}
Please note: Employee is here my custom class having properties same as queried.
Theres a nuget package that may help you "System.Linq.Dynamic". This sample code works...
public class TestRow
{
public Dictionary<string,float> Field { get; set; }
public TestRow()
{
this.Field = new Dictionary<string, float>();
this.Field.Add("ColumnA", 2);
this.Field.Add("ColumnB", 3);
}
}
class Program
{
static void Main(string[] args)
{
var testRow = new TestRow();
string expressionString = "r.Field[\"ColumnA\"] * r.Field[\"ColumnB\"]";
var parameter = Expression.Parameter(typeof(TestRow),"r");
var lambdaET = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { parameter }, typeof(float), expressionString);
var result = lambdaET.Compile().DynamicInvoke(testRow);
Console.WriteLine(result);
Console.ReadLine();
}
}

Create an Array from SQL Query Results

I have the following function that searches a database for entries where a column called "description" have the same value. Right now it just returns the first value it finds or a default value is there isn't one.
public static NewCode GetAltCode(int altCodeVer, string descrip)
{
var sql = #"select Code, Description, VersionID from Code.CodeLookup where versionid=#vers and description=#description";
return ObjectFactory.GetInstance<IDatabaseFactory>().Query<NewCode>(sql, new { vers = altCodeVer, description = descrip, }).FirstOrDefault();
}
I have this if statement to check and make sure the result isn't null, and if it is, to say that the "code isn't found"
[Authorize(parentAction: "Edit")]
public ActionResult Lookup(string Code, int? VersionId = null)
{
var Info = VisitViews.GetDescriptionByVersionId(Code, VersionId.HasValue ? VersionId.Value : 9);
var description = string.Empty;
// CHECK FOR NULL
if (Info != null)
{
description = Info.Description;
if (VersionId == 9)
{
var altInfo = VisitViews.GetAltCode(10, description);
}
if (VersionId == 10)
{
var altInfo = VisitViews.GetAltCode(9, description);
}
}
else
description = "CODE NOT FOUND";
return Json(new { Description = description });
}
My question is, instead of doing FirstOrDefault, is there a way to store the results in an array (or even to store them in a list and call ToArray on the list)? I'm trying to get all of the codes received during the sql search instead of just one so that another function I am working on can traverse the array and place the items where they need to be in a UI.
For future reference of this post, here is the answer:
Change the return type to NewCode[] and replace .FirstOrDefault() with .ToArray()
public static NewCode[] GetAltCode(int altCodeVer, string descrip)
{
var sql = #"select Code, Description, VersionID from Code.CodeLookup where versionid=#vers and description=#description";
return ObjectFactory.GetInstance<IDatabaseFactory>().Query<NewCode>(sql, new { vers = altCodeVer, description = descrip, }).ToArray();
}

Linq to Sql: How to quickly clear a table

To delete all the rows in a table, I am currently doing the following:
context.Entities.DeleteAllOnSubmit(context.Entities);
context.SubmitChanges();
However, this seems to be taking ages. Is there a faster way?
You could do a normal SQL truncate or delete command, using the DataContext.ExecuteCommand method:
context.ExecuteCommand("DELETE FROM Entity");
Or
context.ExecuteCommand("TRUNCATE TABLE Entity");
The way you are deleting is taking long because Linq to SQL generates a DELETE statement for each entity, there are other type-safe approaches to do batch deletes/updates, check the following articles:
Batch Updates and Deletes with LINQ to SQL
LINQ to SQL Extension: Batch Deletion with Lambda Expression
Unfortunately LINQ-to-SQL doesn't execute set based queries very well.
You would assume that
context.Entities.DeleteAllOnSubmit(context.Entities);
context.SubmitChanges();
will translate to something like
DELETE FROM [Entities]
but unfortunately it's more like
DELETE FROM [dbo].[Entities] WHERE ([EntitiesId] = #p0) AND ([Column1] = #p1) ...
DELETE FROM [dbo].[Entities] WHERE ([EntitiesId] = #p0) AND ([Column1] = #p1) ...
DELETE FROM [dbo].[Entities] WHERE ([EntitiesId] = #p0) AND ([Column1] = #p1) ...
You'll find the same when you try to do bulk update in LINQ-to-SQL. Any more than a few hundred rows at a time and it's simply going to be too slow.
If you need to do batch operations & you're using LINQ-to-SQL, you need to write stored procedures.
I like using an Extension Method, per the following:
public static class LinqExtension
{
public static void Truncate<TEntity>(this Table<TEntity> table) where TEntity : class
{
var rowType = table.GetType().GetGenericArguments()[0];
var tableName = table.Context.Mapping.GetTable(rowType).TableName;
var sqlCommand = String.Format("TRUNCATE TABLE {0}", tableName);
table.Context.ExecuteCommand(sqlCommand);
}
}
you could also use this:
Public void BorraFilasTabla()
{
using(basededatos db = new basededatos())
{
var ListaParaBorrar = db.Tabla.Tolist();
db.Tabla.RemoveRange(ListaParaBorrar);
}
}
The Below c# code is used to Insert/Update/Delete/DeleteAll on a database table using LINQ to SQL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace PracticeApp
{
class PracticeApp
{
public void InsertRecord(string Name, string Dept) {
LinqToSQLDataContext LTDT = new LinqToSQLDataContext();
LINQTOSQL0 L0 = new LINQTOSQL0 { NAME = Name, DEPARTMENT = Dept };
LTDT.LINQTOSQL0s.InsertOnSubmit(L0);
LTDT.SubmitChanges();
}
public void UpdateRecord(int ID, string Name, string Dept)
{
LinqToSQLDataContext LTDT = new LinqToSQLDataContext();
LINQTOSQL0 L0 = (from item in LTDT.LINQTOSQL0s where item.ID == ID select item).FirstOrDefault();
L0.NAME = Name;
L0.DEPARTMENT = Dept;
LTDT.SubmitChanges();
}
public void DeleteRecord(int ID)
{
LinqToSQLDataContext LTDT = new LinqToSQLDataContext();
LINQTOSQL0 L0;
if (ID != 0)
{
L0 = (from item in LTDT.LINQTOSQL0s where item.ID == ID select item).FirstOrDefault();
LTDT.LINQTOSQL0s.DeleteOnSubmit(L0);
}
else
{
IEnumerable<LINQTOSQL0> Data = from item in LTDT.LINQTOSQL0s where item.ID !=0 select item;
LTDT.LINQTOSQL0s.DeleteAllOnSubmit(Data);
}
LTDT.SubmitChanges();
}
static void Main(string[] args) {
Console.Write("* Enter Comma Separated Values to Insert Records\n* To Delete a Record Enter 'Delete' or To Update the Record Enter 'Update' Then Enter the Values\n* Dont Pass ID While Inserting Record.\n* To Delete All Records Pass 0 as Parameter for Delete.\n");
var message = "Successfully Completed";
try
{
PracticeApp pa = new PracticeApp();
var enteredValue = Console.ReadLine();
if (Regex.Split(enteredValue, ",")[0] == "Delete")
{
Console.Write("Delete Operation in Progress...\n");
pa.DeleteRecord(Int32.Parse(Regex.Split(enteredValue, ",")[1]));
}
else if (Regex.Split(enteredValue, ",")[0] == "Update")
{
Console.Write("Update Operation in Progress...\n");
pa.UpdateRecord(Int32.Parse(Regex.Split(enteredValue, ",")[1]), Regex.Split(enteredValue, ",")[2], Regex.Split(enteredValue, ",")[3]);
}
else
{
Console.Write("Insert Operation in Progress...\n");
pa.InsertRecord(Regex.Split(enteredValue, ",")[0], Regex.Split(enteredValue, ",")[1]);
}
}
catch (Exception ex)
{
message = ex.ToString();
}
Console.Write(message);
Console.ReadLine();
}
}
}

Categories