how to check data is present or not in xamarin database - xamarin.android

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.

Related

query nested property of a list in MongoDB with C# Driver

I have a mongodb structured in this way :
public class CarModel
{
[BsonElement("Carname")]
public string Carname { get; set; }
[BsonElement("Color")]
public string Color { get; set; }
[BsonElement("Price")]
public string Price { get; set; }
}
public class Producer
{
[BsonId]
public ObjectId ID { get; set; }
[BsonElement("Producer")]
public string Producer { get; set; }
[BsonElement("CarModel")]
public List<CarModel> CarModel { get; set; }
}
I've made an asp.net core MVC application for make CRUD operation on this database.
now i want to insert a new list of CarModel inside a Producer, but before i want to check if one of the Carname present on this list is already present inside the DB :
[HttpPost]
public ActionResult CreateListino(Producer listino)
{
try
{
var document = _dbContext._database.GetCollection<Producer>("ListinoAuto");
var builder = Builders<Producer>.Filter;
long count = 0;
foreach (var item in listino.CarModel)
{
var filter = builder.Eq(x => x.Producer, listino.Producer) & builder.Where(b => b.CarModel.Any(a => a.Carname == item.Carname));
count += document.Find(filter).CountDocuments();
}
if (count == 0)
{
//Do Something
}
else
{
TempData["Message"] = "Car model Already exist";
return View("CreateListino", listino);
}
return RedirectToAction("Index");
}
catch (Exception e)
{
return View();
}
}
i really don't like to use the foreach statement for loop trough the CarModel received by the view, so I'm asking if there is a metod to compare the List and the database in one single query.
i want to look at only carname, not the other properies.
thank you

ASP.NET Web API and MongoDB Atlas - Method to Retrieve Specific Data from Database

I have created an ASP.NET Web API project (using .NET Framework 4.6.1) in Visual Studio Community Edition 2017 that utilizes MongoDb Atlas via the MongoDB .NET Driver. The project stores "Patients" with a few different attributes.
I have successfully implemented a Get() method to return a "Patient". I now want to implement a GetMedications() method to return only the medications of a particular "Patient". Below are the pertinent methods in my "PatientsController" file:
public async Task<Patient> Get(string id)
{
try
{
ObjectId internalId = GetInternalId(id);
return await _patients.Find(p => p.Id == id || p.InternalId == internalId).FirstOrDefaultAsync();
}
catch (Exception ex)
{
throw ex;
}
}
[Route("api/patients/{id}/medications")]
public async Task<Medication> GetMedications(string id)
{
try
{
ObjectId internalId = GetInternalId(id);
var patient = await _patients.Find(p => p.Id == id || p.InternalId == internalId).FirstOrDefaultAsync();
return patient.Medications;
}
catch (Exception ex)
{
throw ex;
}
}
private ObjectId GetInternalId(string id)
{
ObjectId internalId;
if (!ObjectId.TryParse(id, out internalId))
internalId = ObjectId.Empty;
return internalId;
}
Visual studio displays this error for return patient.Medications:
Cannot implicitly convert type 'Systems.Collections.Generic.ICollection<WebAPIDemo.Models.Medication>' to 'WebAPIDemo.Models.Medication'
Here is my Patient class (and other applicable classes):
public class Patient
{
[BsonId]
public ObjectId InternalId { get; set; }
public string Id { get; set; }
public string Name { get; set; }
public ICollection<Ailment> Ailments { get; set; }
public ICollection<Medication> Medications { get; set; }
}
public class Medication
{
public string Name { get; set; }
public int Doses { get; set; }
}
public class Ailment
{
public string Name { get; set; }
}
How could I properly write the GetMedications() method?
Your problem is that you are returning a collection when your method only returns one item, so you need to make sure the types match.
Change the return type of your method:
public async Task<ICollection<Medication>> GetMedications(string id)

Xamarin - SQLite.SQLiteException: malformed database schema

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

Inserting to tables except where records already exist

I'm looking to add records to my database but not sure of the best approach.
Here are my models:
public class fList
{
public int fListID { get; set; }
public string Title { get; set; }
public int UserID { get; set; }
public ICollection<Item> Items { get; set; }
}
public class Item
{
public int ItemID { get; set; }
public string Name { get; set; }
public ICollection<fList> fLists { get; set; }
}
public class User
{
public int UserID { get; set; }
public string UserName { get; set; }
public ICollection<fList> fLists { get; set; }
}
Here is the database before performing the operation:
Here is how the database should look after performing the operation:
What I want to do is add a new fList and new User. I also want to add new Items but only where they don't already exist. And I want to join Items to the fList accordingly.
I'm hoping to achieve the above as efficiently as possible with minimal db calls.
Here's the controller so far:
var flist = new fList
{
Title = "Colors",
UserName = "Chris"
Items = new List<Item>()
};
flist.Items.Add(new Item { Name = "White" });
flist.Items.Add(new Item { Name = "Orange" });
flist.Items.Add(new Item { Name = "Purple" });
flist.Items.Add(new Item { Name = "Blue" });
flist.Items.Add(new Item { Name = "Green" });
foreach (var item in flist.Items)
{
// Check item exists in database
var existingitem = db.Items.SingleOrDefault(n => n.Name == item.Name);
// If item doesn't exist, add it to database
if (existingitem == null) {
db.Items.Add(item);
}
// ...What next?
}
db.fLists.Add(flist);
db.SaveChanges();
If you have time, you can download the Prodinner sample from Microsoft, it is a perfect solution include OOP, DI, IOC,etc. It also show you the generic functions for saving data.
If you need control the state during save records, you need implement state control your own. Create Interface, Enum and Implement class as show below.
public interface IDataObjectWithState
{
State State { get; set; }
}
public enum State
{
Added,
Unchanged,
Modified,
Deleted
}
public abstract class DataObjectWithState : IDataObjectWithState
{
[NotMapped]
public State State { get; set; }
}
After that any model class you want control the state you need inherit this Class, so your models have extra UnMap State columns.
In your DB Context file, make a contractor as sample below.
public Db()
: base("name=TP_HOST")
{
try
{
((IObjectContextAdapter)this).ObjectContext
.ObjectMaterialized += (sender, args) =>
{
var entity = args.Entity as IDataObjectWithState;
if (entity != null)
{
entity.State = YourEnumNamespace.State.Unchanged;
}
};
}
catch (Exception ex)
{
}
finally { }
}
// this class need include using System.Data.Entity.Infrastructure;
public static EntityState ConvertState(YourEnumNamespace.State state)
{
switch (state)
{
case YourEnumNamespace.State.Added:
return EntityState.Added;
case YourEnumNamespace.State.Deleted:
return EntityState.Deleted;
case YourEnumNamespace.State.Modified:
return EntityState.Modified;
default:
return EntityState.Unchanged;
}
}
Then before you make the call of db.SaveChanges(), you have to set the state like sample below
foreach (var entry in dbContext.ChangeTracker
.Entries<IDataObjectWithState>())
{
IDataObjectWithState stateInfo = entry.Entity;
entry.State =Functions.ConvertState(stateInfo.State);
}
I know difficult to understand mine code, what I want to mention is we define our own enum state, we tell the models what we want (Add, Unchanged, Update, Delete), using for loop change the state become knowing by System.Data.Entity.Infrastructure.

Implementing OnContextCreated for auditing by assigning SaveChanges an eventhandler using EF 4.1 DBContext

I have tried many different ways and looked at different posts, but still haven't come across a solution for this way of auditing. Below is my DBContext template file. I customised it by adding the OnContextCreated() partial method and assign the SavingChanges event to my OnSavingChanges event handler.
namespace ARSystem.Models
{
public partial class ARSEntities : ObjectContext
{
public ARSEntities()
: base("name=ARSEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public string UserName { get; set; }
List<DBAudit> auditTrailList = new List<DBAudit>();
public enum AuditActions
{
I,
U,
D
}
partial void OnContextCreated()
{
this.SavingChanges += new EventHandler(OnSavingChanges);
}
public void OnSavingChanges(object sender, EventArgs e)
{
IEnumerable<ObjectStateEntry> changes = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified);
foreach (ObjectStateEntry stateEntryEntity in changes)
{
if (!stateEntryEntity.IsRelationship &&
stateEntryEntity.Entity != null &&
!(stateEntryEntity.Entity is DBAudit))
{//is a normal entry, not a relationship
DBAudit audit = this.AuditTrailFactory(stateEntryEntity, UserName);
auditTrailList.Add(audit);
}
}
if (auditTrailList.Count > 0)
{
foreach (var audit in auditTrailList)
{//add all audits
this.AddToDBAudit(audit);
}
}
}
private DBAudit AuditTrailFactory(ObjectStateEntry entry, string UserName)
{
DBAudit audit = new DBAudit();
audit.AuditId = Guid.NewGuid().ToString();
audit.RevisionStamp = DateTime.Now;
audit.TableName = entry.EntitySet.Name;
audit.UserName = UserName;
if (entry.State == EntityState.Added)
{//entry is Added
audit.NewData = GetEntryValueInString(entry, false);
audit.Actions = AuditActions.I.ToString();
}
else if (entry.State == EntityState.Deleted)
{//entry in deleted
audit.OldData = GetEntryValueInString(entry, true);
audit.Actions = AuditActions.D.ToString();
}
else
{//entry is modified
audit.OldData = GetEntryValueInString(entry, true);
audit.NewData = GetEntryValueInString(entry, false);
audit.Actions = AuditActions.U.ToString();
IEnumerable<string> modifiedProperties = entry.GetModifiedProperties();
//assing collection of mismatched Columns name as serialized string
audit.ChangedColumns = XMLSerializationHelper.XmlSerialize(modifiedProperties.ToArray());
}
return audit;
}
private string GetEntryValueInString(ObjectStateEntry entry, bool isOrginal)
{
if (entry.Entity is EntityObject)
{
object target = CloneEntity((EntityObject)entry.Entity);
foreach (string propName in entry.GetModifiedProperties())
{
object setterValue = null;
if (isOrginal)
{
//Get orginal value
setterValue = entry.OriginalValues[propName];
}
else
{
//Get orginal value
setterValue = entry.CurrentValues[propName];
}
//Find property to update
PropertyInfo propInfo = target.GetType().GetProperty(propName);
//update property with orgibal value
if (setterValue == DBNull.Value)
{//
setterValue = null;
}
propInfo.SetValue(target, setterValue, null);
}//end foreach
XmlSerializer formatter = new XmlSerializer(target.GetType());
XDocument document = new XDocument();
using (XmlWriter xmlWriter = document.CreateWriter())
{
formatter.Serialize(xmlWriter, target);
}
return document.Root.ToString();
}
return null;
}
public EntityObject CloneEntity(EntityObject obj)
{
DataContractSerializer dcSer = new DataContractSerializer(obj.GetType());
MemoryStream memoryStream = new MemoryStream();
dcSer.WriteObject(memoryStream, obj);
memoryStream.Position = 0;
EntityObject newObject = (EntityObject)dcSer.ReadObject(memoryStream);
return newObject;
}
public DbSet<Student> Students { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<aspnet_Applications> aspnet_Applications { get; set; }
public DbSet<aspnet_Membership> aspnet_Membership { get; set; }
public DbSet<aspnet_Roles> aspnet_Roles { get; set; }
public DbSet<aspnet_SchemaVersions> aspnet_SchemaVersions { get; set; }
public DbSet<aspnet_Users> aspnet_Users { get; set; }
public DbSet<vw_aspnet_Applications> vw_aspnet_Applications { get; set; }
public DbSet<vw_aspnet_MembershipUsers> vw_aspnet_MembershipUsers { get; set; }
public DbSet<vw_aspnet_Roles> vw_aspnet_Roles { get; set; }
public DbSet<vw_aspnet_Users> vw_aspnet_Users { get; set; }
public DbSet<vw_aspnet_UsersInRoles> vw_aspnet_UsersInRoles { get; set; }
public DbSet<Cours> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Modules> Modules { get; set; }
public DbSet<EnrollmentsByCourse> EnrollmentsByCourse { get; set; }
public DbSet<EnrollmentsByCourseAudit> EnrollmentsByCourseAudit { get; set; }
public DbSet<DBAudit> DBAudit { get; set; }
}
}
However, when I compile, i get the error message that:
Error 1 'ARSystem.Models.ARSEntities.OnModelCreating(System.Data.Entity.DbModelBuilder)': no suitable method found to override C:\Users\mngum\Documents\Visual Studio 2010\Projects\ARSystem\ARSystem\Models\ARSystem.Context.cs 35 33 ARSystem
I cannot see the OnContextCreated method in the DBContext metadata class but i can find it in the edmx designer. Please let me know how i can implement the OnContextCreated() method such that I can override the SavingChanges event for auditing purposes.
DbContext does not have an OnContextCreated event but that's not a problem because you don't need it to achieve the same. Instead with DbContext the SaveChanges method is overridable. So instead of your OnSavingChanges event handler you use:
public override int SaveChanges()
{
// custom code...
return base.SaveChanges();
}
This method will be called whenever you call ARSEntities.SaveChanges() and you can perform custom actions before you call the base.SaveChanges() of the base DbContext (ARSEntities must be derived from DbContext of course.)
You also can access the underlying ObjectContext from the DbContext:
public override int SaveChanges()
{
var objectContext = ((IObjectContextAdapter)this).ObjectContext;
// use methods and properties of ObjectContext now like
// objectContext.ObjectStateManager, etc.
// custom code...
return base.SaveChanges();
}
Here was a similar question and answer about change auditing with EF 4.1/DbContext:
Entity Framework 4.1 DbContext Override SaveChanges to Audit Property Change

Resources