How to drop table in Xamarin from sqlite database - c#

I am unable to drop tables completely from sqLite database in XAMARIN using command db.DropTable<tablename>. It gets dropped at first but appears again every time I restart the application. Also I have multiple tables with the same name and I need to drop them all. What should I do?
I am developing an android application in Visual Studio using XAMARIN and C#.
Unfortunately I created many tables with the same name. Now I need to drop them.
I am using following code to create tables and database:-
namespace Test
{
[Table("OrderDetails")]
public class OrderDetails
{
[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
[MaxLength(50)]
public string payeename { get; set; }
[MaxLength(100)]
public string commodity { get; set; }
public int give { get; set; }
public int take { get; set; }
public DateTime date { get; set; }
}
[Activity(Label = "Test", MainLauncher = true)]
public class MainActivity : Activity
{
[Table("Items")]
public class PayeeMaster
{
[PrimaryKey, AutoIncrement, Column("_id")]
public int Id { get; set; }
[MaxLength(8)]
public string FirstName { get; set; }
[MaxLength(8)]
public string LastName { get; set; }
}
SQLiteConnection db;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
CreateDatabase();
}
public bool ifExists_Table(string tablename)
{
SQLiteCommand command = db.CreateCommand("SELECT COUNT(1) FROM SQLITE_MASTER WHERE TYPE = #TYPE AND NAME = #NAME");
command.Bind("#TYPE", "table");
command.Bind("#NAME", tablename);
int result = command.ExecuteQuery<int>();
return (result > 0);
}
public void CreateDatabase() {
try
{
string dbPath = Path.Combine(
System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal),
"Master.db3");
db = new SQLiteConnection(dbPath);
}
catch (IOException ex)
{
var reason = string.Format("The database failed to create -
reason {0}", ex.Message);
}
if (!ifExists_Table("PayeeMaster"))
{
db.CreateTable<PayeeMaster>();
}
else
{
var count = db.Table<PayeeMaster>().Count();
}
if (!ifExists_Table("OrderDetails"))
{
db.CreateTable<OrderDetails>();
}
else {
var count = db.Table<OrderDetails>().Count();
}
}
}

I finally understand the problem, sorry for the confusion.
First of all - doing Table<T>().Count() doesn't actually check for table existence, but instead checks if the table contains any rows.
To actually check if the table exists, you will have to do an actual SQL query:
private bool DoesTableExist(string name)
{
    SQLiteCommand command = _connection.CreateCommand("SELECT COUNT(1) FROM SQLITE_MASTER WHERE TYPE = #TYPE AND NAME = #NAME");
    command.Bind("#TYPE", "table");
    command.Bind("#NAME", name);
    int result = command.ExecuteScalar<int>();
    return (result > 0);
}

Related

Nested one-to-many tables SQLite-Net Extensions [duplicate]

I am trying to use SQLite-Net Extensions to create a Relational Database. I'm running into an issue when trying to pull the Term object from the database. It successfully pulls over its associated courses, but not the courses associated assessments and notes. I'm not sure if the problem lies in how I insert the objects into the database, how I pull the objects from the database, or how I have the objects attributes listed.
I feel like the SQLite-Net Extensions documentation is extremely limited, so I'm not even sure what's going on. I've tried it many different ways, including adding CascadeOperations, but non of those seemed to help.
Here is the (simplified) code for my objects:
[Table("Terms")]
public class Term
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set; }
[OneToMany]
public List<Course> Courses { get; set; }
public Term() { }
public Term(string name, List<Course> courses)
{
Name = name;
Courses = courses;
}
Courses
[Table("Courses")]
public class Course
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
[ForeignKey(typeof(Term))]
public int TermID { get; set; }
public string Name { get; set; }
[OneToMany]
public List<Assessment> Assessments { get; set; }
[OneToMany]
public List<Note> Notes { get; set; }
public Course() { }
public Course(string name, List<Assessment> assessments, List<Note> notes)
{
Name = name;
Assessments = assessments;
Notes = notes;
}
}
Assessments
[Table("Assessments")]
public class Assessment
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
[ForeignKey(typeof(Course))]
public int CourseID { get; set; }
public string Name { get; set; }
public Assessment() { }
public Assessment(string name)
{
Name = name;
}
}
Notes
[Table("Notes")]
public class Note
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
[ForeignKey(typeof(Course))]
public int CourseID { get; set; }
public string Name { get; set; }
public string Text { get; set; }
public Note() { }
public Note(string name, string note)
{
Name = name;
Text = note;
}
}
And here is the code for inserting and getting objects:
Inserting
public bool SaveTermAsync(Term term)
{
if (term.ID != 0)
{
_database.UpdateWithChildrenAsync(term);
return true;
}
else
{
foreach (var course in term.Courses)
{
foreach (var assessment in course.Assessments)
{
_database.InsertAsync(assessment);
}
foreach (var note in course.Notes)
{
_database.InsertAsync(note);
}
_database.InsertAsync(course);
}
_database.InsertAsync(term);
_database.UpdateWithChildrenAsync(term);
return false;
}
}
Getting
public Task<List<Term>> GetTermsAsync()
{
return _database.GetAllWithChildrenAsync<Term>();
}
I know it's a bit of a code dump, but I have no idea where or what could be going wrong. If anyone could give any information about what is potentially going wrong, that would be awesome. Perhaps I'm simply expecting something to happen that isn't actually how it works. I don't know.
Also, if anyone has any links to some better documentation than https://bitbucket.org/twincoders/sqlite-net-extensions/src/master/ that would be awesome
EDIT
I tried using Cascading Options as well, CascadeRead, CascadeInsert, and CascadeAll. Using CascadeInsert or CascadeAll with _database.InsertWithChildrenAsync(term, true) resulted in a crash. The crash does not provide any error messages, and even wrapping the InsertWithChildren with a try catch block didn't work. Removing the recursive bool caused the program not to crash, and actually get the closest to what I'm looking for. Assessments and Notes are no longer null, but are still empty. Here's my updated code:
Saving and Getting:
public async Task<List<Term>> GetTermsAsync()
{
return await _database.GetAllWithChildrenAsync<Term>(recursive: true);
}
public async void SaveTermAsync(Term term)
{
if (term.ID != 0)
{
await _database.UpdateWithChildrenAsync(term);
}
else
{
//Trying this with recursion results in crash
await _database.InsertWithChildrenAsync(term);
}
}
One-To-Many Relationships:
//In Term
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Course> Courses { get; set; }
//In Courses
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Assessment> Assessments { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<Note> Notes { get; set; }
Also, I forgot to include last time how I'm populating the tables in the first place.
public bool CreateTables()
{
_database.CreateTableAsync<Term>().Wait();
_database.CreateTableAsync<Course>().Wait();
_database.CreateTableAsync<Assessment>().Wait();
_database.CreateTableAsync<Note>().Wait();
return true;
}
public Task<int> ClearTablesTest()
{
_database.DropTableAsync<Term>();
_database.DropTableAsync<Course>();
_database.DropTableAsync<Assessment>();
return _database.DropTableAsync<Note>();
}
async public Task<int> PopulateTestData()
{
await ClearTablesTest();
CreateTables();
Term term = new Term("Test Term", true, DateTime.Now, DateTime.Now.AddDays(10),
new List<Course>
{
new Course("Test Course", CourseStatus.Completed, "Guys Name", "(999)-999-9999", "email#gmail.com", 6, DateTime.Now, DateTime.Now.AddDays(10),
new List<Assessment>
{
new Assessment("Test Assessment", AssessmentType.Objective, false, DateTime.Now, DateTime.Now.AddDays(10))
},
new List<Note>
{
new Note("Test Note", "This is a test note.")
})
});
App.Database.SaveTermAsync(term);
return 0;
}
I finally figured out what was causing the crash as well as causing general confusion within SQLite-Net Extensions.
In my Assessment class, the property
public string BackgroundColor
{
get { return IsComplete ? "#558f45" : "Gray"; }
set { BackgroundColor = value; }
}
was causing the crash when recursion was used. I've been scouring the web for over two weeks looking for solutions to this issue, but haven't found anything similar to this. I submitted a bug report on the SQLite-Net Extensions bitbucket.
If anyone knows why this specific line would cause issues, I'd love to hear your input. Until then I'm going to mark this question as answered and continue work on my app.
Thanks #redent84 for your help thus far on this issue.

Error when try to insert value in database with NPoco

I am using this example from Umbraco docs and when i try to save values to the database table i am getting this error:
Cannot insert the value NULL into column 'Id', table 'petapoco.dbo.BlogComments'; column does not allow nulls. INSERT fails. The statement has been terminated.
Also, after table is created and i check it in database, I can see that primary key and autoincrement option is not set for id field.
And this is how i insert values:
public class Class1 : IUserComposer
{
public void Compose(Composition composition)
{
composition.Components().Append<SubscribeToContentServiceSavingComponent>();
}
public class SubscribeToContentServiceSavingComponent : IComponent
{
public void Initialize()
{
MemberService.Saved += MemberService_Saving;
}
public void Terminate()
{
}
private void MemberService_Saving(IMemberService sender, SaveEventArgs<IMember> e)
{
foreach (IMember member in e.SavedEntities)
{
var blogPostToAdd = new BlogCommentSchema();
blogPostToAdd.BlogPostUmbracoId = member.Id;
blogPostToAdd.Name = member.Name;
blogPostToAdd.Email = member.Name;
blogPostToAdd.Website = member.Name;
blogPostToAdd.Message = member.Name;
using (var scope = Current.ScopeProvider.CreateScope(autoComplete:true))
{
var database = scope.Database;
// use database
scope.Database.Insert<BlogCommentSchema>(blogPostToAdd);
scope.Complete();
}
}
}
}
}
Good guy on Umbraco forum solved my problem. This is the missing part in my class:
[PrimaryKeyColumn(AutoIncrement = true, IdentitySeed = 1)]
So my class finally should look like this:
[TableName("BlogComments")]
[PrimaryKey("Id", AutoIncrement = true)]
[ExplicitColumns]
public class BlogCommentSchema
{
[PrimaryKeyColumn(AutoIncrement = true, IdentitySeed = 1)]
[Column("Id")]
public int Id { get; set; }
[Column("BlogPostUmbracoId")]
public int BlogPostUmbracoId { get; set; }
[Column("Name")]
public string Name { get; set; }
[Column("Email")]
public string Email { get; set; }
[Column("Website")]
public string Website { get; set; }
[Column("Message")]
[SpecialDbType(SpecialDbTypes.NTEXT)]
public string Message { get; set; }
}
}

How to insert data from MS Access to SQL after checking whether the data exists or not in the database using Entity Framework

Hopefully, the question header is clear enough to tell that I'm trying to read an Access file and upload the data to the database but checking at first whether the data already exists or not in the database.
I receive a daily report from a third-party company in Access file. I'm trying to create a windows service that will check for the file every morning, and if the new file exist, then it'll read and upload the data to the database. I'm trying to use Entity Framework. I read the article on Navigation Property, but I'm still confused on that; I never used navigation property before. Here are my models:
[Table("ClaimsTable")]
public partial class ClaimsTable
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int ClaimsID { get; set; }
public string EOPAID { get; set; }
public string AuthID { get; set; }
public string PAStatus { get; set; }
public string UserName { get; set; }
[DataType(DataType.Date)]
public DateTime EffectiveDate { get; set; }
[DataType(DataType.Date)]
public DateTime EndDate { get; set; }
public string RecordType { get; set; }
public int RxID { get; set; }
public int MemberID { get; set; }
public int PrescriberID { get; set; }
public string EditNumber { get; set; }
public string OriginSource { get; set; }
public string OriginMethod { get; set; }
/*
[ForeignKey("RxID")]
public virtual RxTable Prescription { get; set; }
[ForeignKey("MemberID")]
public virtual MembersTable Member { get; set; }
[ForeignKey("PrescriberID")]
public virtual PrescribersTable Prescriber { get; set; }
*/
}
...
[Table("MembersTable")]
public partial class MembersTable
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int MemberID { get; set; }
[DataType(DataType.Date), Display(Name= "Date of Birth"), DisplayFormat(DataFormatString="{0:mm/dd/yyyy}", ApplyFormatInEditMode=true)]
public DateTime DateofBirth { get; set; }
public string CardholderID { get; set; }
public string MemberFirstName { get; set; }
public string MemberLastName { get; set; }
//public virtual ICollection<AddressTable> Address { get; set; }
}
...
[Table("PrescribersTable")]
public partial class PrescribersTable
{
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int PrescriberID { get; set; }
public string NPI { get; set; }
public string PrescriberFirstName { get; set; }
public string PrescriberLastName { get; set; }
public string PhysicianType { get; set; }
//public ICollection<AddressTable> Address { get; set; }
}
....
using(OleDbConnection conn = new OleDbConnection(strDSN))
{
OleDbDataReader reader = null;
OleDbCommand command = new OleDbCommand("Select * from table", conn);
try
{
conn.Open();
}
catch(OleDbException o)
{
return o.Message;
}
reader = command.ExecuteReader();
List<ClaimsTable> Claim = new List<ClaimsTable>();
List<PrescribersTable> PrescriberInDB = new List<PrescribersTable>();
List<MembersTable> MembersInDB = new List<MembersTable>();
while(reader.Read())
{
PrescriberInDB = context.Prescribers.ToList();
MembersInDB = context.Members.ToList();
//CREATE LOCAL VARIABLE
string recordType = //check if the member and the prescriber exist in the database
int prescriberID = 0;
int prodID = 0;
int memberID = 0;
int drugID = 0;
int RxID = 0;
int claimID = 0;
//check if the member and the prescriber exist in the object before inserted into the database.
//the data will be uploaded to the database in bulk
//int newPrescriberID = Prescriber.Where(x => x.PrescriberFirstName == reader["Prescriber First Name"] && x.PrescriberLastName == reader["Prescriber Last Name"] && x.NPI == reader["Prescribing Physician"]).Select(x => x.PrescriberID).FirstOrDefault();
//int newMemberID = Member.Where(x => x.MemberFirstName == reader["Member First Name"] && x.MemberLastName == reader["Member Last Name"] && x.CardholderID == reader["CardhHolder"]).Select(x => x.MemberID).FirstOrDefault();
//insert the data if it doesn't exist
if(!PresciberExist(prescriberFirstName, prescriberLastName, npi, PrescriberInDB))
{
var prescriber = new PrescribersTable()
{
PrescriberFirstName = prescriberFirstName,
PrescriberLastName = prescriberLastName,
NPI = npi,
PhysicianType = physicianType
};
context.Prescribers.Add(prescriber);
context.SaveChanges();
prescriberID = GetPrescriberID(prescriberFirstName, prescriberLastName, physicianType, PrescriberInDB);
}
if(!MemberExist(memberFirstName, memberLastName, cardholderID, MembersInDB))
{
var member = new MembersTable()
{
MemberFirstName = memberFirstName,
MemberLastName = memberLastName,
CardholderID = cardholderID,
DateofBirth = dob
};
context.Members.Add(member);
context.SaveChanges();
memberID = GetMemberID(memberFirstName, memberLastName, cardholderID, MembersInDB);
}
}
}
return "Done uploading";
}
private bool MemberExist(string memberFirstName, string memberLastName, string cardholderID, List<MembersTable> MembersInDB)
{
return MembersInDB.Exists(x => x.MemberFirstName == memberFirstName && x.MemberLastName == memberLastName && x.CardholderID == cardholderID);
}
private bool PresciberExist(string prescriberFirstName, string prescriberLastName, string npi, List<PrescribersTable> PrescriberInDB)
{
return PrescriberInDB.Exists(x => x.PrescriberFirstName == prescriberFirstName && x.PrescriberLastName == prescriberLastName && x.NPI == npi);
}
The access database contains sensitive information, so I won't be able to add those data as an example. But here's a made up data for test. The data contains claims of patients.
Now, because there are many drugs and many claims for the same patient, and many patients for a prescriber.. I broke the database as it's shown above. Needs improvement? I welcome suggestion. The reason I did this is because I don't want my database to have repeated records which will make managing really troubling. This way, I'll have unique members in memberstable, unique prescribers in prescriberstable and so on and so forth.
The challenge I'm facing is that when I read the data from the access database, I'm assuming it reads row-wise. The code should first check the database whether the member exist or not. If it does, then get the member id which is an identity column. If it doesn't, then it should insert the member's info only, and then get the memberID. Similarly, I do the same thing with the prescriber's data. Check and insert if needed. This is the long way, and this is the only way I could figure out how to do it.
I know this is not a very good programming. I'm just an analyst who unfortunately has to do a lot of programming. And I'm learning as I go. With that said, there's a lot of ways to improve this code - I just don't know any. Can you point me to the right direction? Also, an example of how to check and insert the data if it doesn't exist in the database using navigation property. Currently, the data is read and uploaded just fine, but I saw in the database that it didn't quite do what I wanted it to do. It still added a couple of already existing members. I seriously needs some help.

Error inserting record with entity framework

I am sorry if it has already been answered but I can't find any solution. Here is my (little) problem. Also all my apologies if the terms I use are approximate, I am far from being a skilled C# developer
Note that I think my problem is similar to this one Entity Framework validation error for missing field, but it's not missing?
I have a table "Tweets" with a tweet_id field (bigint) which is my primary key.
I use the following class to load the table :
class TwitterDbContext : DbContext
{
public TwitterDbContext() : base("Twitter")
{
}
public DbSet<Stream> Streams { get; set; }
public DbSet<StreamParameter> StreamParameters { get; set; }
public DbSet<Tweet> Tweets { get; set; }
}
public class Tweet
{
public Tweet()
{
}
[Key]
public long tweet_id { get; set; }
public string tweet { get; set; }
public long creator { get; set; }
public double latitude { get; set; }
public double longitude { get; set; }
public string language { get; set; }
public DateTime created_at { get; set; }
public DateTime registered_at { get; set; }
public long? in_reply_to { get; set; }
public bool retweeted { get; set; }
}
I have an other class to store within the code execution all the fields used by the Tweet table. For the need here, let's imagine I manually create it that way
private void Test_Button_Click(object sender, RoutedEventArgs e)
{
Twts twtReceived = new Twts();
twtReceived.tweet_id = 1;
twtReceived.tweet = "test";
twtReceived.creator = 1;
twtReceived.latitude = -1;
twtReceived.longitude = -1;
twtReceived.language = "a";
twtReceived.created_at = DateTime.Now;
twtReceived.registered_at = DateTime.Now;
twtReceived.in_reply_to = 1;
twtReceived.retweeted = true;
AddTweet(twtReceived);
}
Now here is the AddTweet method
static public void AddTweet(Twts twtReceived)
{
try
{
// update the tweet data in the database
using (var TwitterDb = new TwitterDbContext())
{
Tweet twt = new Tweet()
{
tweet_id = twtReceived.tweet_id,
tweet = twtReceived.tweet,
creator = twtReceived.creator,
longitude = twtReceived.longitude,
latitude = twtReceived.latitude,
language = twtReceived.language,
created_at = twtReceived.created_at,
registered_at = twtReceived.registered_at,
in_reply_to = twtReceived.in_reply_to,
retweeted = twtReceived.retweeted
};
TwitterDb.Tweets.Add(twt);
TwitterDb.SaveChanges();
}
}
catch(Exception ex)
{
MessageBox.Show(ex.InnerException.ToString());
}
}
I constantly have the same error message:
Cannot insert the value NULL into column 'tweet_id', table
'Twitter.dbo.Tweets'; column does not allow nulls. INSERT fails.
The thing is that when I spy on "TwitterDb.Tweets.Local" after TwitterDb.Tweets.Add(twt); I correctly have tweet_id set to 1.
Any idea where is the issue?
Try marking your tweet_id field with following (instead of just [Key]), if this is a primary key column where you want to provide values yourself
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
If it is an auto-increment, then remove explicit assignments to this field and mark it as 'Identity' instead:
[Required, Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]

Specified table does not exist

I'm searching for an answer to this question. I don't know where is the problem. Visual Studio does not see any problem or error, but when I run program and try to add something to database, application crashes and VS tell me that my table does not exist. That event is for adding something.
This is my code:
private void addBtn_Click(object sender, RoutedEventArgs e)
{
using (WpisyDataContext BazaDanych = new WpisyDataContext(strConnectionString))
{
if (!BazaDanych.DatabaseExists())
{
BazaDanych.CreateDatabase();
MessageBox.Show("BazaDanych Database Created Successfully!!!");
}
Wpis newWpis = new Wpis
{
RecordID = index_box.Text,
NameRec = name_box.Text.ToString(),
BeneficiaryRec = beneficiary_box.Text.ToString(),
PriceRec = price_box.Text.ToString(),
DeadlineRec = deadline_box.Text.ToString(),
DescriptionRec = description_box.Text.ToString()
};
BazaDanych.Wpisy.InsertOnSubmit(newWpis);
BazaDanych.SubmitChanges();
MessageBox.Show("Recoed Added Successfully!!!");
if (NavigationService.CanGoBack)
{
NavigationService.GoBack();
}
}
}
}
This is the table code (Wpis.cs):
using System.Data.Linq.Mapping;
namespace ********
{
[Table]
public class Wpis
{
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public string RecordID
{
get;
set;
}
[Column(CanBeNull = true)]
public string NameRec
{
get;
set;
}
[Column(CanBeNull = true)]
public string BeneficiaryRec
{
get;
set;
}
[Column(CanBeNull = true)]
public string PriceRec
{
get;
set;
}
[Column(CanBeNull = true)]
public string DeadlineRec
{
get;
set;
}
[Column(CanBeNull = true)]
public string DescriptionRec
{
get;
set;
}
}
}
And this is the data context (WpisyDataContext.cs):
using System.Data.Linq;
namespace *************
{
public class WpisyDataContext : DataContext
{
public WpisyDataContext(string connectionString)
: base(connectionString)
{
}
public Table<Wpis> Wpisy
{
get
{
return this.GetTable<Wpis>();
}
}
}
}
This is connection string:
public static string strConnectionString = #"Data Source=isostore:/DevDB.sdf";
Please guys, I don't have any more patience. Thanks.
When you use CreateDatabase(), please check whether .Net has created the database table as your Entity. Because EntityFramework create table with Plural name and Entity is created with singular name.
Check whether the created table name is as expected.

Categories

Resources