Xamarin - SQLite.SQLiteException: malformed database schema - xamarin.android

I am trying to set password to my database in Xamarin.Android project here is sample of my code after include Sqlcipher
First install works just fine but when I close app and re-open it , app crashes with this error
SQLite3.Prepare2
android.runtime.JavaProxyThrowable: SQLite.SQLiteException: malformed database schema (Items) - unrecognized token: "]"
my sample code
private async void CreateDb()
{
string requireFlag = SharedPreManager<string>.GetSingleton(this).RetrieveAccessKey(DSPPublicKeys.REQUIRE_ALTER_KEY, "true").ToString();
//Creating database, if it doesn't already exist
if (!File.Exists(_dbPath))
{
await _logic.CreateDb(_dbPath);
}
else if (File.Exists(_dbPath) && DSPPublicKeys.REQUIRE_ALTER_Client && requireFlag.Equals("true"))
{
DeleteDb();
await _logic.CreateDb(_dbPath);
SharedPreManager<string>.GetSingleton(this).SaveAccessKey(DSPPublicKeys.REQUIRE_ALTER_KEY, "false");
}
if (db == null)
{
db = new SQLiteAsyncConnection(_dbPath);
}
// set password to database
var t = db.QueryAsync<int>("PRAGMA key=123456").Wait(-1);
if (NetworkUtils.IsNetworkConnected(ApplicationContext))
_logic.MigrateDataFromBackend(db);
}
Table definition
[Table("Items")]
public class Item
{
[PrimaryKey , Column("ID")]
public long ID { get; set; }
[Column("TradeNameEn")]
public string TradeNameEn { get; set; }
[Column("TradeNameNative")]
public string TradeNameNative { get; set; }
[Column("GenericName")]
public string GenericName { get; set; }
[Column("TimeStamp")]
public long TimeStamp { get; set; }
[Column("BaseUnitPrice")]
public decimal BaseUnitPrice { get; set; }
}
any one can guide me why this error raised here

Related

The entity type <type> is not part of the model from the current context

I get this error (An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code
The entity type tblMessage is not part of the model for the current context.) and have tried fixes I found online but they didnt seem to help. I also did somethin similar for another database tabel earlier in the code.
Im trying to retrieve messages form my database table called tblMessages.
Constructor:
public JsonResult ConversationWithContact(int contact)
{
if (Session["UserID"] == null)
{
return Json(new {status = "error", message = "User is not logged in"});
}
//var currentUser = (Models.tblUser)Session["UserID"];
var conversations = new List<Models.tblMessage>();
using (var db = new Models.ChatContext())
{
int currentUserId = (int)Session["UserID"];
var currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
conversations = db.Conversations.Where(c => (c.receiverId == currentUser.Id
&& c.senderId == contact) ||
(c.receiverId == contact
&& c.senderId == currentUser.Id))
.OrderBy(c => c.created_at)
.ToList();
}
return Json(
new {status = "success", data = conversations},
JsonRequestBehavior.AllowGet
);
}
Context:
public ChatContext() : base("TrinityEntities")
{
}
public static ChatContext Create()
{
return new ChatContext();
}
public DbSet<tblUser> Users { get; set; }
public DbSet<tblMessage> Conversations { get; set; }
Database model class:
public class tblMessage
{
public tblMessage()
{
status = messageStatus.Sent;
}
public enum messageStatus
{
Sent,
Delivered
}
public int Id { get; set; }
public int senderId { get; set; }
public int receiverId { get; set; }
public string message { get; set; }
public messageStatus status { get; set; }
public System.DateTime created_at { get; set; }
}
Here is issue with Table Mapping to database. each entity will be set up to map to a table with the same name as the DbSet<TEntity> property that exposes to the derived context. If no DbSet<TEntity> is included for the given entity, the class name is used.
as you set in your code Users and Conversations is not table name. for that you can customize also refere https://learn.microsoft.com/en-us/ef/core/modeling/relational/tables
and use Data Annotations for specify table name.
public messageStatus status { get; set; }
i think this property is not not part of your table column so you have to specify [NotMapped] Data Annotations.
after changes and adding Data Annotations to table context and table look likes.
public class ChatContext : DbContext
{
public ChatContext()
{
}
public virtual DbSet<tblUser> Users { get; set; }
public virtual DbSet<tblMessage> Conversations { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=test;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
}
and your models(tables) entities look like.
[Table("tblMessage")]
public class tblMessage
{
public tblMessage()
{
status = messageStatus.Sent;
}
public enum messageStatus
{
Sent,
Delivered
}
public int Id { get; set; }
public int senderId { get; set; }
public int receiverId { get; set; }
public string message { get; set; }
[NotMapped]
public messageStatus status { get; set; }
public System.DateTime created_at { get; set; }
}
[Table("tblUser")]
public class tblUser
{
public int id { get; set; }
public string name { get; set; }
}
now you can access your Conversations and Users after adding [Table("<table-name>")] Data-Annotations.
also you can use Fluent API for table mapping.
after using table mapping table after debug code image like.
i hope it helps you and let me know if require any more information. :)

how to check data is present or not in xamarin database

Hello everyone i Have implemented sqlite database in xamarin and i need to search taht any specfic data is present or not in database.
I want to check that if data or row is there or not in database according to the album key
Here is my Database class
namespace FacebookAuth
{
class DatabaseHelper
{
Java.IO.File dir = new Java.IO.File(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/Android/data/com.abhijit.testing.app/databases");
public bool createDataBase()
{
try
{
using (var connection = new SQLiteConnection(Path.Combine(dir.AbsolutePath, "album.db")))
{
connection.CreateTable<AlbumTable>();
return true;
}
}
catch (SQLiteException e)
{
return false;
}
}
public bool InsertIntoTable(AlbumTable album)
{
try
{
System.Console.Write("Data Saved Successfully");
using (var connection = new SQLiteConnection(Path.Combine(dir.AbsolutePath, "album.db")))
{
connection.Insert(album);
return true;
}
}
catch (SQLiteException e)
{
return false;
}
}
public List<AlbumTable> getalldata()
{
try
{
using (var connection = new SQLiteConnection(Path.Combine(dir.AbsolutePath, "album.db")))
{
return connection.Table<AlbumTable>().ToList();
}
}
catch (SQLiteException ex)
{
return null;
}
}
public List<AlbumTable> SelectAlbum(string orderid)
{
try
{
using (var connection = new SQLiteConnection(Path.Combine(dir.AbsolutePath, "album.db")))
{
return connection.Query<AlbumTable>("SELECT * From album Where AlbumKey=?", orderid);//not working exception raised that invalid table name
}
}
catch (SQLiteException ex)
{
return null;
}
}
public bool DeleteFromTable(AlbumTable album)
{
try
{
System.Console.Write("Data Saved Successfully");
using (var connection = new SQLiteConnection(Path.Combine(dir.AbsolutePath, "album.db")))
{
connection.Delete(album);
return true;
}
}
catch (SQLiteException e)
{
return false;
}
}
}
}
and the column name for database is as follows
K
class AlbumTable
{
[PrimaryKey]
public string Id { get; set; }
public string ZipFillPath { get; set; }
public string CoverPhotoPath { get; set; }
public string AlbumKey { get; set; }
public string NoOfPages { get; set; }
public string Email { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string City { get; set; }
public string Address1 { get; set; }
public string ZipPostalCode { get; set; }
public string PhoneNumber { get; set; }
}
How to check that value is present in db or not
Open Android Device Monitor from Tools->Android->Android Device Monitor
Navigate to your database file and copy out the database file into your PC.
You can open the database using any SQLite browser to check whether your data is in the DB. e.g. http://sqlitebrowser.org/
The docs are quite good at giving easy-to-follow instructions.
You need your id column to be an int, then you can use the Get<T>() method
public List<AlbumTable> SelectAlbum(int orderid)
{
try
{
using (var connection = new SQLiteConnection(Path.Combine(dir.AbsolutePath, "album.db")))
{
return connection.Get<AlbumTable>(orderid);
}
}
catch (SQLiteException ex)
{
return null;
}
}
If you wish to use Sql (see next point as to why you may want to), you need to create the table with a defined name, otherwise the name given to the table may well be some programmatically-created non-human-friendly internal gibberish.
[Table("Albums")]
class AlbumTable
{
[PrimaryKey]
public int Id { get; set; }
...
If you have to keep the id column as a string (that is you have no control over the database) you could use a linq get
return connection.Get<AlbumTable>().FirstOrDefault(a => a.Id == orderid);
Note that this loads all the data into memory and so will be horrible for performance if you get a large amount of data in the database as well as loosing the inbuilt advantages of databases - storing and searching data is what they are built for. This is not Entity Framework and so for complex queries, use direct Sql statements as above.

umbraco 7 insert row in custom table

I have just made a model and controller which insert new row in a custom table to my umbraco database.
I based it on petapoco tutorial http://creativewebspecialist.co.uk/2013/07/16/umbraco-petapoco-to-store-blog-comments/
Despite the script executing without errors the row is not inserted into the table.
here's what I have:
namespace MyImport.Models
{
[TableName("MyImport_Uploads")]
[PrimaryKey("ID", autoIncrement = true)]
[ExplicitColumns]
public class ImportFile
{
[Column("ID")]
[PrimaryKeyColumn(AutoIncrement=true)]
public int Id { get; set; }
[Required]
[Column("CompanyID")]
public string CompanyId { get; set; }
//public Guid CompanyId { get; set; }
[Required]
[Column("FilenameOriginal")]
public string FilenameOriginal { get; set; }
[Required]
[Column("Filename")]
public string Filename { get; set; }
[Required]
[Column("FileType")]
public string FileType { get; set; }
[Column("NumberOfItems")]
public int NumberOfItems { get; set; }
[Column("DateCreated")]
public DateTime DateCreated { get; set; }
[Column("DeleteExisting")]
public bool DeleteExisting { get; set; }
}
}
And controller:
namespace MyImport.Controllers
{
public class ImportController : SurfaceController
{
private Umbraco.Core.Persistence.UmbracoDatabase db = MyImport.Settings.UmbracoDbDSN;
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult ImportExcel(ImportModel model)
{
var fileTypes = new List<string>
{
"text/xml",
"application/xml",
};
string fileType = GetFileType(model.FileUpload.ContentType);
if(model.FileUpload != null && model.FileUpload.ContentLength > 0)
{
string uploadDir = "~/imports";
string origFileName = model.FileUpload.FileName;
string extension = origFileName.Substring(origFileName.LastIndexOf('.') + 1);
string pathToCheck = Path.Combine(Server.MapPath(uploadDir), origFileName);
// Check to see if a file already exists with the
// same name as the file to upload.
if (!System.IO.File.Exists(pathToCheck))
{
string companyId = MyImport.Member.CompanyIdDummy;
string tempfileName = companyId.ToLower() + "-" + DateTime.Now.ToString("yyyyMMddHHmmss") + "." + extension;
pathToCheck = Path.Combine(Server.MapPath(uploadDir), tempfileName);
model.FileUpload.SaveAs(pathToCheck);
var importFile = new ImportFile
{
CompanyId = companyId,
Filename = tempfileName,
FilenameOriginal = origFileName,
FileType = extension,
DateCreated = DateTime.UtcNow
};
db.Insert(importFile);
}
TempData.Add("Success", true);
}
//redirect to current page to clear the form
return RedirectToCurrentUmbracoPage();
}
}
Any suggestions? Thanks
I had the database wrongly set up.
Basically I had it as umbraco.sdf in App_Data folder while I intended to use my full MSSQL database where the table was created.
I recreated the project, reinstalled umbraco and HAD to choose Customize at the bottom of the screen where I was choosing setting up cms access. This is important as I was then directed to the screen where I could set up my database connection.
Otherwise umbraco just install into SQL Server Express database which is stored in umbraco.sdf file in the project.
I hope this make sense for anyone looking for the solution to the same problem.

Adding two new elements to a List in Entity Framework

In my model, I have the following Section class:
public partial class Section
{
public Section()
{
Steps = new List<SectionStep>();
}
public int Id { get; set; }
public int SortId { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Html { get; set; }
public Nullable<int> Tutorial_Id { get; set; }
[JsonIgnore]
public virtual Tutorial Tutorial { get; set; }
public virtual ICollection<SectionStep> Steps { get; set; }
[NotMapped]
public bool _destroy { get; set; }
}
and the following SectionStep class:
public class SectionStep
{
public int Id { get; set; }
public int SortId { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public string Html { get; set; }
[JsonIgnore]
public virtual Section Section { get; set; }
[NotMapped]
public bool _destroy { get; set; }
}
I have an ASP.NET application in which users can edit these, including adding and removing Sections and SectionSteps. The data is POSTed to the server via JSON, the server reads this correctly and adds everything just fine. However, when I add two SectionSteps to the same section, I get the following error:
An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key.
The JSON POSTed to the server is deserialized into List<Section> sections The following code handles this and adds the appropriate objects to my entity model.
foreach (Section section in sections)
{
if (section._destroy)
{
// if id is 0, it was never even added
if (section.Id > 0)
db.Entry(section).State = EntityState.Deleted;
}
else if (section.Id == 0)
{
db.Entry(section).State = EntityState.Added;
}
else
{
db.Entry(section).State = EntityState.Modified;
}
foreach (SectionStep step in section.Steps.ToList())
{
if (step._destroy)
{
// if id is 0, it was never even added so don't delete
if (step.Id > 0)
db.Entry(step).State = EntityState.Deleted;
else
section.Steps.Remove(step);
}
else if (step.Id == 0)
{
db.Entry(step).State = EntityState.Added;
db.SaveChanges();
}
else
{
db.Entry(step).State = EntityState.Modified;
}
}
}
db.SaveChanges();
returnSections.AddRange(db.Sections.Where(s => s.Tutorial_Id == tutorial_id).OrderBy(s => s.SortId).ToArray());
It seems to me that the problem is that when I add two steps, they both have the same Id for some reason. At first they do start with Id = 0 because I let the database automatically assign that, but I handle the Sections the same way, and adding two Sections works just fine.

MVC 4 Web API NullException Error (Noobie)

I'm working on my first MVC 4 app, following the MVC First Web API Tutorial on Asp.net. I've left the names the same, but changed the model and controller code. Here's my model:
public class Product
{
public string SID { get; set; }
public string name { get; set; }
public string givenName { get; set; }
public string sn { get; set; }
public string mail { get; set; }
public string telephoneNumber { get; set; }
public string mobile { get; set; }
public string otherMobile { get; set; }
public string title { get; set; }
public string Manager { get; set; }
public DateTime whenChanged { get; set; }
}
public class ProductModel
{
public ProductModel()
{
ProductList = new List<Product>();
}
public IList<Product> ProductList { get; set; }
}
And here's my APIcontroller:
public class ProductsController : ApiController
{
ProductModel products = new ProductModel();
public IEnumerable<Product> GetAD()
{
DirectoryEntry domainRoot = new DirectoryEntry(LDAP_server);
DirectorySearcher searcher = new DirectorySearcher(searchStr);
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult srchResult in results)
{
DirectoryEntry dirEntry = srchResult.GetDirectoryEntry();
if (dirEntry.Properties["givenName"].Value != null && dirEntry.Properties["sn"].Value != null && !dirEntry.Parent.Name.Contains("Terminated"))
{
products.ProductList.Add(new Product()
{
SID = dirEntry.Properties["sid"].Value.ToString(),
name = dirEntry.Properties["name"].Value.ToString(),
givenName = dirEntry.Properties["givenName"].Value.ToString(),
sn = dirEntry.Properties["sn"].Value.ToString(),
mail = dirEntry.Properties["mail"].Value.ToString(),
telephoneNumber = dirEntry.Properties["telephoneNumber"].Value.ToString(),
mobile = dirEntry.Properties["mobile"].Value.ToString(),
otherMobile = dirEntry.Properties["otherMobile"].Value.ToString(),
title = dirEntry.Properties["title"].Value.ToString(),
Manager = dirEntry.Properties["Manager"].Value.ToString(),
whenChanged = Convert.ToDateTime(dirEntry.Properties["whenChanged"].Value.ToString()),
});
}
}
return products.ProductList;
}
}
I'm getting the NullException on 'products.ProductList.Add(new Product()', am I missing something simple? Please forgive my coding, as I'm just trying to get this up and running, thanks.
the problem mostly likely is dealing with dirEntry, not Web API itself. rather than introduce LDAP into this, just create a bunch of dummy products to return.
FYI... there is also a memory leak issue with the use of LDAP objects. They need to be properly disposed of, both along the happy path and if an exception is thrown.
I'm an idiot. 'sid' is not the correct property name from AD, it is 'objectSid', thus always returning a null. I knew it was something simple.

Resources