Creating an SQLite table programmatically - c#

I am creating a Xamarin Forms application. The application contains a button which creates a new list. The list's name and date is saved in one table but the list's contents must be stored in another table, which needs to be created using a query. I have been able to successfully insert records into the table that holds the names and dates of the lists using the following approach:
[Table("ToDoLists")]
public class ShoppingList : INotifyPropertyChanged
{
private int _id;
[PrimaryKey, AutoIncrement]
public int Id
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged(nameof(Id));
}
}
private string _name;
[NotNull]
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged(nameof(Name));
}
}
private string _date;
[NotNull]
public string Date
{
get
{
return _date;
}
set
{
_date = value;
OnPropertyChanged(nameof(Date));
}
}
private string _description;
[NotNull]
public string Description
{
get
{
return _description;
}
set
{
_description = value;
OnPropertyChanged(nameof(Description));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
I have tried the following things:
Pass on the list name as a table name in the [Table(tableName)] statement but the IDE tells me that only constant fields are allowed to be used, meaning that I can't dynamically specify a table name
I have tried reading about SQLiteCommand but the examples I'm given use functions that aren't available in SQLite PCL (unless I've installed SQLite PCL incorrectly).
How exactly do I create a table using a query in SQLite PCL? Is it even possible? Any suggestions?

Take a look at SQLite-net:
SQLite-net is an open source, minimal library to allow .NET and Mono applications to store data in SQLite 3 databases. It was first designed to work with Xamarin.iOS, but has since grown up to work on all the platforms (Xamarin.*, .NET, UWP, Azure, etc.).
SQLite-net was designed as a quick and convenient database layer. Its
design follows from these goals:
Very easy to integrate with existing projects and runs on all the .NET platforms.
Thin wrapper over SQLite that is fast and efficient. (This library should not be the performance bottleneck of your queries.)
Very simple methods for executing CRUD operations and queries safely (using parameters) and for retrieving the results of those
query in a strongly typed fashion.
Works with your data model without forcing you to change your classes. (Contains a small reflection-driven ORM layer.)
First, create a SQLiteAsyncConnection to your database:
private SQLiteAsyncConnection database;
database = new SQLiteAsyncConnection("YourDatabasePath");
Then you can use the method CreateTableAsync() to create your table:
await database.CreateTableAsync<ShoppingList>();
For adding data to the table, you can do something like this:
public async Task SaveShoppingObjects(List<ShoppingObjects> shoppingsObjects)
{
await database.RunInTransactionAsync(tran =>
{
foreach (ShoppingObject s in shoppingObjects)
{
tran.InsertOrReplace(SqliteEntityFactory.Create(s));
}
});
}
SqliteEntityFactory.Create is a method which helps you creating the table element. It could look something like this:
public static ShoppingList Create(ShoppingObject s)
{
ShoppingList slist = new ShoppingList();
if (s == null)
{
return slist;
}
slist.Id = s.Id;
slist.Name = s.Name;
// etc...
return slist;
}
If I understand your question right, that should make the trick!

Related

What is the best way of having a 'DataService' class that handles all connections and database updates

I think this should be a simple thing to do, but it's doing my head in. It's a Windows Forms app in C#.
I have created a 'DataService' class that implements and fills a number of DataSets that I defined using VS's Dataset Designer.
I then pass those datasets to business objects that can display, update, add and delete rows in those datasets, then have 'DataService' handle the .AcceptChanges(). None of my tables are large.
It is working perfectly, except that updates are never being committed back to the database (MS-Access).
I have tried using 'get/set' to pass the datasets to the business classes. The datasets are being correctly updated, and I can see the updates back in the 'DataService' class in debug mode.
I've researched extensively, but most implementations with a separate data service are much more abstract than this. My idea was to only have one copy of the dataset ever instantiated, so that the DataService class would see the updates and commit them with dataset.AcceptChanges().
Of course I probably haven't implemented that correctly (even if it's a workable option), because updates don't get committed - the Access database is never updated.
In the example below, I have one Dataset dsWLQueues with two datatables. dsWLQueues was created in Dataset Designer which generates all the update etc statements...
Can someone help with my understanding?
Thanks
public class DataService
{
// Class to handle all data retrievals and management
private static dsWLQueues dslWLQueues = new dsWLQueues();
public static dsWLQueues Queues {get { return dslWLQueues; } set { dslWLQueues = value; dslWLQueues.AcceptChanges(); } }
public static void LoadAllData()
{
dsWLQueuesTableAdapters.SongQueueNamesTableAdapter daSongQueueNames = new dsWLQueuesTableAdapters.SongQueueNamesTableAdapter();
dslWLQueues.Clear();
daSongQueueNames.Fill(dslWLQueues.SongQueueNames);
dsWLQueuesTableAdapters.SongQueuesTableAdapter daSongQueues = new dsWLQueuesTableAdapters.SongQueuesTableAdapter();
daSongQueues.Fill(dslWLQueues.SongQueues);
}
Then to use this class:
public class QueueList : System.Windows.Forms.UserControl
{
private dsWLQueues dsSongQueues;
dsSongQueues = DataService.Queues;
...some code that displays and updates/deletes/adds data...
DataService.Queues = dsSongQueues;
}
I was using DataAdapter.AcceptChanges() that only updates the in-memory dataset. I needed to use DataAdapter.Update instead.
Now the solution works perfectly. I have a DataService that loads all DataTables and makes them available via methods to all other classes.
Doh!
public static DataTable Codes { get { return dtWLCodes; } }
public static DataTable Songs { get { return dtWLSongs; } }
public static DataTable SongLyrics { get { return dtWLSongLyrics; } }
public static void Commit (string sTable = "")
{
if (sTable == "" || sTable == "Songs") { daWLSongs.Update(dslWLSongs.Songs); }
if (sTable == "" || sTable == "SongLyrics") { daWLSongLyrics.Update(dslWLSongs.SongLyrics); }

How to use C# WPF?

For my school assignment I have to make a reservationsystem for a hotel.
The thing is that I have to make the code without the UI (never done this before).
I have to add the UI later. Each UI should be able to be used with my code.
Now I have a class called Secretary
The Secretary is able to make a Reservation.
I have this method in the class Secretary :
public void CheckIn()
{
Reservation reservation = new Reservation();
reservation.ReservationDate1 = //info from a textbox
}
Now I know that I should connect everything when my UI is ready, but what is the best way to tell my code that he should get the information from the textbox when the textbox isn't there yet???
i would suggest you start by reading this
now as for what you have to do then
first you will need to model your data
public class Reservation
{
public DateTime Date{get;set;}
public string Name{get;set;}
public void Save(){/*Copy entry to DB, webservice, file, etc*/}
public void Delete(){/*delete entry from DB, webservice, file, etc*/}
//ect
}
as you can see you now have a list of what is required for a reservation, and functionality that will persist your data
next you need a ViewModel
public class ReservationViewModel:INotifyPropertyCHanged
{
public Reservation Reservation{get;set;} //Link to model
private DateTime _Date;
public DateTime Date
{
get { return _Date; }
set { SetProperty(ref _Date, value); }
}
private string _Name;
public string Name
{
get { return _Name; }
set { SetProperty(ref _Name, value); }
}
public void SetProperty<T>(ref T store, T value,[CallerMemberName] string name = null)
{
store = value;
if(PropertyChanged!=null)PropertyChanged(this,new PropertyChangedArgs(name);
}
public void Save(){/*validate, copy over model values call models save*/}
public void Cancel(){/*change VM values back to Model values*/}
public void Delete(){/*validate, call models delete*/}
//ect
}
at this point you can stop as you have defined the data and behaviour of the system, though i would suggest adding a testing project to run your code and check it works
when you get to your View
you would just bind to your ViewModel and the rest is done for you
<TextBox Text={Binding Name}/>
You can use MVVM with a ViewModel, but if you just want a method ready to accept input when you design the UI, you can make Checkin() take a string parameter so it's Checkin(string value) and assign value to ReservationDate1.
public void CheckIn(string val)
{
Reservation reservation = new Reservation();
reservation.ReservationDate1 = val;
}
This is an exercise in keeping your logic and your UI nice and separate. A little more tightly coupled, but doable, would be this:
public void CheckIn(TextBox tb)
{
Reservation reservation = new Reservation();
reservation.ReservationDate1 = tb.Text;
}

How to access output parameter values for IParameterMapper?

Relational Database: Sql Server 2008
Programming Language: C#
Used Framework: Enterprise Library 5.0
How do you access output parameters that are created within the implementation of IParameterMapper?
I'm currently implementing the Repository Pattern. All of our Insert stored procedures contain an output parameter. The output parameter is only present in for those tables who's primary key is an auto generated identity column. All of my stored procedures have associated implementations of IParameterMapper. Each table has an associated TransferObject. Each TransferObject has an associated IRowMapper implementation.
If it is impossible to access the output parameter I believe I only have two other options.
1) Change the stored procedures to return a row that contains the newly created identity as opposed to returning the value through an output parameter. By doing it this way I can use the currently implemented IRowMapper to access the value in the application layer. This way would be more resource intensive but less programming will be needed within the repository.
2) Don't use Database.ExecuteSprocAccessor and just execute the stored procedure "normally"; keeping the stored procedures as they are. This would be the most efficient solution, but require more programming effort.
Below is an example of how we are currently implementing things.
Current Implementation
public class UserRepository : IRepository<User>
{
....
public void Insert(User user)
{
this.database.
}
....
}
public class User : TransferObject
{
public string ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class UserRowMapper : IRowMapper<User>
{
private static readonly UserRowMapper instance = new UserRowMapper();
private UserRowMapper()
{
}
public UserRowMapper Instance
{
get
{
return instance;
}
}
public User MapRow(IDataRecord row)
{
var user = new User
{
ID = row.GetInt32("ID"),
FirstName = row.GetString("FirstName"),
LastName = row.GetString("LastName")
};
}
}
public class InsertUserParameterMapper : IParameterMapper
{
private static readonly InsertUserParameterMapper instance = new InsertUserParameterMapper();
public InsertUserParameterMapper()
{
}
public static InsertUserParameterMapper Instance
{
get
{
return instance;
}
}
public void AssignParameters(DBCommand command, object[] parameterValues)
{
var firstNameParameter = command.CreateParameter();
firstNameParameter.ParameterName = "#firstName";
firstNameParameter.Direction = ParameterDirection.Input;
parameter.Value = parameterValues[0];
command.Parameters.Add(firstNameParameter);
var lastNameParameter = command.CreateParameter();
lastNameParameter.ParameterName = "#lastName";
lastNameParameter.Direction = ParameterDirection.Input;
parameter.Value = parameterValues[1];
command.Parameters.Add(lastNameParameter);
var idParameter = command.CreateParameter();
idParameter.ParameterName = "#id";
idParameter.Direction = ParameterDirection.Output;
command.Parameters.Add(idParameter);
}
}
Output parameters were explicitly not included in the accessor design. If your sproc uses them, you're much better off calling the sproc directly.
Considering you're using this with an insert sproc, I suspect it's not returning rows anyway, so the accessor is really not the right abstraction. You want a straight sproc call.
Having said that, you can still use your input mapper if you want - it doesn't have any particular dependency on an accessor, you could call it directly, passing a DbCommand object instead. But db.ExecuteNonQuery does effectively what you're doing already anyway, so you might just get shorter code out of the deal.

The "Model" in .Net MVC

How do data frameworks such as Linq 2 SQL, ADO.Net Data Entities and DataSets relate to the "Model" as defined by .Net MVC.
The reason I ask is I'm trying to learn the ins and outs of the .Net framework without relying on many of the tools that make it easy and hide the workings from you.
The "model" I'm building in my exploratory app is simply PostgreSQL commands to update the database. I'm purposefully not using a data "framework".
I'm finding that much of the functionality that comes as part of the .Net MVC framework isn't working for me. Stuff like UpdateModel() and anything related to ModelState doesn't seem to acknowledge what's going on.
Is much of that functionality tied to using Linq 2 SQL or ADO.Net Data Entities? If so, that's fine, I just don't quite understand the relationship yet.
Unlike Views and Controllers, there's not really any restrictions on what the Model is in an ASP.NET MVC app. It just enables you to model the data in your app and clearly and safely express your intent without having to resort to using dictionaries such as ViewData to pass data around.
In terms of the model-related functionality, I believe (not 100% sure) that it is based on having public properties on your model objects. If you call UpdateModel or its relatives, it will set public properties on the model object based on the form data etc. All it does it set properties on that in-memory object if it finds appropriate ones that match form inputs etc. You still need to include the logic to actually persist that to a database or whatever else it is you want to do.
Hope this points you in the right direction at least.
Basically your "Model" object needs to have a parameterless constructor and public get/set properties for it to function easily with the DefaultModelBinder.
Tip: I believe that if you fail to define a parameterless constructor, an empty one is inferred for you (just so you don't freak out: "ahh! i don't hav a parameterless constructor").
So this would generally work fine:
public class Customer
{
public int ID { get; set; }
public string Name { get; set; }
public string Number { get; set; }
public string Email { get; set; }
}
Figured it out. For the sake of completeness...
Ok, so there is a "minimum standard" for models in .Net.
This is NOT accepted as a model:
namespace MVCApplication.Models
{
public class Person
{
public int ID;
public string Name;
public string Title;
public string Description;
public string Phone;
public string Address;
public string Country;
public Person()
{
}
}
}
This IS accepted as a model:
namespace MVCApplication.Models
{
public class Person
{
private int _ID;
private string _Name;
...
public Person() {}
public int ID { get{ return _ID } set{ this._ID = value } }
public int Name { get{ return _Name } set{ this._Name = value } }
...
}
}
I can't say I completely understand why, but at least now I know.

Problem with repository creation in C# and ADO.NET entities

I'm building this app at night after work and have been struggling with this design problem for a week or two now.
I'm building a program that has 44 different types of entries and requires the ability to create a custom type.
Because users might change the fields in a particular type of entry and/or define their own, my first approach of generating an Entity class for each type of entry doesn't seem workable. If users change any of the fields or their version of the schema (subject to validation, of course) then my classes wouldn't really reflect that.
Even if did not allow users to change fields, I want to make sure that data schema changes do not create problems for current data.
In order to build a schema capable of all of this, I have done the following:
dtype
id
datatype
field
id fieldName
fieldDataType (linked by foreign key to dtype)
dataStore
id
dataText
dataString
dataDate
dataDouble
dataInt
fieldID (linked by foreign key to field)
entryID (linked by foreign key to id field of entries)
types
ol>id int
typeName
fields
entries
id
typeid (linked by foreign key to id of types)
Well, the schema is very denormalized but difficult to work with in ASP.NET MVC.
My second crack at it involved making a class with typed properties to store whichever datatype the entry happened to be.
Custom Class for domain level
public class entry
{
public List dataList = new List();
public entry(int id)
{
kleraDataContext s = new kleraDataContext();
var dataSet = s.dataStores.Where(c => c.citationID == id);
foreach (dataStore y in dataSet)
{
dataBlob tempd = new dataBlob();
//We get the data type id
var temp = s.fields.Where(c => c.id == y.fieldID).First();
//Get the fieldname and store the data type id for later
tempd.fieldname = temp.fieldName;
tempd.dataType = temp.dtype.dataType;
switch (tempd.dataType)
{
case "String":
tempd.dString = y.dataString;
break;
case "Text":
tempd.dString = y.dataText;
break;
default:
//Nothing
break;
}
this.dataList.Add(tempd);
}
}
}
public class dataBlob
{
private string _dString;
private DateTime _dDate;
private int _dInt;
private double _dDouble;
private object _data;
private string _fieldname;
private string _dataType;
public string dataType
{
get
{
return _dataType;
}
set
{
_dataType = value;
}
}
public object data
{
get
{
return _data;
}
}
public string dString
{
get
{
return _dString;
}
set
{
_dString = value;
_data = value;
}
}
public string fieldname
{
get
{
return _fieldname;
}
set
{
_fieldname = value;
}
}
public DateTime dDate
{
get
{
return _dDate;
}
set
{
_dDate = value;
_data = value;
}
}
public double dDouble
{
get
{
return _dDouble;
}
set
{
_dDouble = value;
_data = value;
}
}
public int dInt
{
get
{
return _dInt;
}
set
{
_dInt = value;
_data = value;
}
}
}
}
Note several problems with this.
I'm having trouble getting a generic enough property to store the data regardless of what field type it is in the physical structure. Ideally, data's accessor would just retrieve whatever the datatype happened to be.
I still don't have a good enough way to provide ASP.NET MVC's views with a coherent enough model so that the presentation code does not have to do parsing. Ideally, the view would just get an object with a list of fields and with their corresponding data.
Related to #2, I can't seem to figure out an appropriate way of persisting changes. Writing a query and having it return the fields to the view could be done. Because each field is not a strongly typed accessor, I'm not sure how to persist the change from the view to the model. Naively, I've thought of inserting a key in a hidden span and using a Dictionary object in the controller to map edits/creation.
Thoughts?
Ron
While I am not exactly sure of your ultimate goal, I may have an option for you. You need a highly dynamic "entity" which will allow your users to create their own data structures. Imperative languages like C# do not lend themselves well to such a thing...and even with a dynamic language, I think you'll likely run into some difficulties. However, XML is an excellent way to represent dynamic data structures in an ad-hoc, runtime-creatable way.
If you are using SQL Server, I recommend you create a simpler type, as depicted below, and store it in a table that uses the 'xml' data type for one of the columns:
public class DynamicEntity
{
public int ID { get; set; }
public string TypeName { get; set; }
public XDocument DynamicContent { get; set; }
}
The above entity could be stored in the following table:
CREATE TABLE DynamicEntity
(
ID int IDENTITY(1,1) NOT NULL,
NAME varchar(50) NOT NULL,
DynamicContent xml NULL
)
Given SQL Server's xml capabilities, you will still be able to query the data in that xml column. Not only that, if you want your users custom structures to be validated against a schema, you could also put that schema in the database and 'type' your xml column against that schema. Using an XML column in SQL Server does come with come caveats, but it might be a simple solution to your otherwise complicated problem.

Categories