SQLite - what and how to? - database

I'm all new to databases and I've heard that SQLite should be straight forward, but I kinda find that not to be the case.
I have a decent knowledge of C# and WPF and I'm trying to make a small personal project which I want to use in daily life. My idea is a program that manages receipts that I bring home.
I have two Models - Item and Receipt
class Item
{
public int Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int ReceiptId { get; set; }
}
class Receipt
{
public int Id { get; set; }
public string Store { get; set; }
public double Price { get; set; }
public DateTime Date { get; set; }
}
My corrent problem is that I've been caught in all the different SQLite "versions" available. I've found that there is ADO.NET and LINQ and some other sorts.. what does these different ones mean and is the programming syntax for each of them different and which would be most suitable for my case?
I'm developing in Visual Studio 2012 and I've managed to download the NuGet SQLite package that goes by the name "System.Data.SQLite (x86/x64)".
I want to create a database, create two tables with these object in them, but I have basicly no idea how to and searching google for a day or two has just me that more confused, since so many people use different syntaxes and most of the tutorials I've find relate to how people used the old "SQLite.dll". So what my question is, is how do I make a database that fits this program structure and how do I write, read, connect and disconnect to my database.

Related

Another efcore violation of primary key constraint reference table problem

Assume I've read and googled, and I still don't know what I'm doing incorrectly. Whenever I try to execute
_dbContext.Set<T>().Add(aMediaObjectWithAssociatedProvider);
_dbContext.SaveChanges();
I get the dreaded efcore violation of primary key constraint reference table
I have a class as such:
public class Media : BaseModel
{
public virtual string Title { get; set; }
public virtual string? Description { get; set; }
public virtual string Source { get; set; }
public virtual Guid? MediaTypeId { get; set; }
public virtual Guid? ProviderId { get; set; }
public virtual DateTime? StartDate { get; set; }
public virtual DateTime? EndDate { get; set; }
public virtual Provider? Provider { get; set; }
}
The BaseModel class is
public abstract class BaseModel : IBaseModel
{
public virtual Guid Id { get; set; }
}
The Provider class is as such:
public class Provider : BaseModel
{
public virtual string Name { get; set; }
public virtual string? ApiUsername { get; set; }
public virtual string? ConfigurationSection{ get; set; }
}
My DBContext has the following:
protected override void OnModelCreating(ModelBuilder mb)
{
mb.Entity<Media>().HasKey(x => x.Id);
mb.Entity<Media>().HasOne(p => p.Provider).WithOne().HasForeignKey<Media>(x => x.ProviderId);
}
The code for inserting a new object is as follows:
public T Insert(T oneObject)
{
try
{
// Ensure the entity has an ID
if (oneObject.Id == Guid.Empty)
{
oneObject.Id = Guid.NewGuid();
}
_dbContext.Set<T>().Add(oneObject);
_dbContext.SaveChanges();
}
catch (Exception error)
{
_logger.LogError(error.Message, error);
}
return oneObject;
}
Assume that providers are static, in a sense that they already exist in their table, and I don't want to add new providers when I save media... Media just needs to have a provider.
I know exactly what is happening (the model, after travelling through json back through the api to the server is losing context, but I'm also trying to build a repository type of system where I don't have to build complex save logic for every object. (hence why i'm hand wringing over adding code that loads existing providers).
This problem specifically began rearing its head when I was saving new Media objects into the database with existing Providers. I am still mulling over how to look up children dynamically, but i'm not quite there yet.
I've been at this for so long, i'm about ready to give up on efcore relations and just rebuild the models as single objects, and handle all of the manipulation in javascript. And I don't like this idea.
I know for a fact that there will be questions for more code, but please let me know what. Again, I'm just stepping into .net core / ef core so this code-first is a little confusing for me. Thanks
You may have 2 options to try. Do backup your whole project and database beforehand. Clone your database to another database name. Try these either one option using new cloned database for testing.
No.1
Set "newid()" without quotes in your ID's default value in sql server. So you don't need to use Guid.NewGuid() in code every insert. newid() will auto generate GUID.
No. 2
How about removing primary key from ID (GUID) and then creating new column "UID" (running number) and set UID (running number) as primary key and enable its identity? You need to change all other tables too. And re-link UID each other if you use relationship. This way, your UID will not have existing number when insert.

optional many to one or zero issue in Entity Framework

I am trying to create a quick demo shop, and I am failing with an optional many to one or zero relationship.
The relevant classes are:
Item
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public int SubCategoryID { get; set; }
public virtual SubCategory Category { get; set; }
public double Price { get; set; }
}
Order
public class Order
{
public int ID { get; set; }
public DateTime DateOfOrder { get; set; }
public virtual ICollection<Item> Items { get; set; }
public int CustomerID { get; set; }
public virtual Customer Customer { get; set; }
}
However, I am getting confused because viewing the model shows:
but, the database itself shows (for items):
Which indicates to me that each item can only belong to a single order.
Do I have to create a separate class that is many to many orders/items?
I seem to remember EF doing this automatically, but, I haven't touched it for a few years and I just can't remember what I used to do.
I had to add:
public virtual ICollection<order> Orders { get; set; }
to the Item... I'm never going to call it this way, but it looks like that is required for EF to build this relationship.
I am sure it used to be easier, so, leaving this question open so someone can give a better answer!
If you add a collection of Orders to the Item entity, EF will create for you implicitly the junction table on your DB. In this page you can find more info about how to configure a many to many relationship.
The junction table generally is mapped when you need to add an additional column (that excludes both keys of the tables you are joining). In that case you need to create two one-to-many relationships between the entity that represent the junction table and Order and Item respectively. Some people recommend always map the junction table because that way you have all the tables represented as entities and you can write queries starting by the junction table. You can find interesting info about this subject in this link. But, in my experience, in most cases you can work perfectly without map explicitly the junction table.

Creating seed model from data already in DB

Is there a way to convert data in an existing database into objects that can easily be put into a seed method?
Essentially I'd like to let some people add lines to my DB via a form and then convert that into an object that I can re-seed the DB anytime I need to make changes.
The database itself is created via code-first using the following model:
public class Combo
{
public int Id { get; set; }
public string MainPrefix { get; set; }
public string MainDescriptor { get; set; }
public string MainDish { get; set; }
public string Connector { get; set; }
public string SecondaryDescriptor { get; set; }
public string SecondaryDish { get; set; }
}
High level untested idea:
Create a new T4 template which will use either your context or direct SQL to query database and generate either C# static class with method (which will return collection of object created from database data) or SQL insert commands. Depending on what you choose you will either call static method in Seed to get all entities you want to insert or simply load the created SQL script and execute it.
You can also do the same without T4 by using Code Dom (if you want to generate C# code) and creating a new custom tool for visual studio.
These features can be part of your project or the result (C# code) can be compiled in separate external assembly.

How would I model data that is heirarchal and relational in a document-oriented database system like RavenDB?

Document oriented databases (particularly RavenDB) are really intriguing me, and I'm wanting to play around with them a bit. However as someone who is very used to relational mapping, I was trying to think of how to model data correctly in a document database.
Say I have a CRM with the following entities in my C# application (leaving out unneeded properties):
public class Company
{
public int Id { get; set; }
public IList<Contact> Contacts { get; set; }
public IList<Task> Tasks { get; set; }
}
public class Contact
{
public int Id { get; set; }
public Company Company { get; set; }
public IList<Task> Tasks { get; set; }
}
public class Task
{
public int Id { get; set; }
public Company Company { get; set; }
public Contact Contact { get; set; }
}
I was thinking of putting this all in a Company document, as contacts and tasks do not have a purpose out side of companies, and most of the time query for a task or contacts will also show information about the associated company.
The issue comes with Task entities. Say the business requires that a task is ALWAYS associated with a company but optionally also associated with a task.
In a relational model this is easy, as you just have a Tasks table and have the Company.Tasks relate to all tasks for the company, while Contact.Tasks only show the tasks for the specific Task.
For modeling this in a document database, I thought of the following three ideas:
Model Tasks as a separate document. This seems kind of anti-document db as most of the time you look at a company or contact you will want to see the list of tasks, thus having to perform joins over documents a lot.
Keep tasks that are not associated with a contact in the Company.Tasks list and put tasks assocaited with a contact in the list for each individual contacts. This unfortunately means that if you want to see all tasks for a company (which will probably be a lot) you have to combine all tasks for the company with all tasks for each individual contact. I also see this being complicated when you want to disassociate a task from a contact, as you have to move it from the contact to the company
Keep all tasks in the Company.Tasks list, and each contact has a list of id values for tasks it is associated with. This seems like a good approach except for having to manually take id values and having to make a sub-list of Task entities for a contact.
What is the recommended way to model this data in a document oriented database?
Use denormalized references:
http://ravendb.net/faq/denormalized-references
in essence you have a DenormalizedReference class:
public class DenormalizedReference<T> where T : INamedDocument
{
public string Id { get; set; }
public string Name { get; set; }
public static implicit operator DenormalizedReference<T> (T doc)
{
return new DenormalizedReference<T>
{
Id = doc.Id,
Name = doc.Name
}
}
}
your documents look like - i've implemented the INamedDocument interface - this can be whatever you need it to be though:
public class Company : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public IList<DenormalizedReference<Contact>> Contacts { get; set; }
public IList<DenormalizedReference<Task>> Tasks { get; set; }
}
public class Contact : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public DenormalizedReference<Company> Company { get; set; }
public IList<DenormalizedReference<Task>> Tasks { get; set; }
}
public class Task : INamedDocument
{
public string Name{get;set;}
public int Id { get; set; }
public DenormalizedReference<Company> Company { get; set; }
public DenormalizedReference<Contact> Contact { get; set; }
}
Now saving a Task works exactly as it did before:
var task = new Task{
Company = myCompany,
Contact = myContact
};
However pulling all this back will mean you're only going to get the denormalized reference for the child objects. To hydrate these I use an index:
public class Tasks_Hydrated : AbstractIndexCreationTask<Task>
{
public Tasks_Hydrated()
{
Map = docs => from doc in docs
select new
{
doc.Name
};
TransformResults = (db, docs) => from doc in docs
let Company = db.Load<Company>(doc.Company.Id)
let Contact = db.Load<Contact>(doc.Contact.Id)
select new
{
Contact,
Company,
doc.Id,
doc.Name
};
}
}
And using your index to retrieve the hydrated tasks is:
var tasks = from c in _session.Query<Projections.Task, Tasks_Hydrated>()
where c.Name == "taskmaster"
select c;
Which i think is quite clean :)
As a design conversation - the general rule is that if you ever need to load the child documents alone as in - not part of the parent document. Whether that be for editing or viewing - you should model it with it's own Id as it's own document. Using the method above makes this quite simple.
I'm new to document dbs as well...so with a grain of salt...
As a contrasting example...if you are on Twitter and you have a list of the people you follow, which contains a list of their tweets...you would not move their tweets into your twitter account in order to read them, and if you re-tweet, you would only have a copy, not the original.
So, in the same way, my opinion is that if Tasks belong to a company, then they stay within the Company. The Company is the Aggregate Root for Tasks. The Contacts can only hold references (ids) or copies of the Tasks and cannot modify them directly. If you have your contact hold a "copy" of the task, that's fine, but in order to modify the task (e.g. mark it complete) you would modify the task through its Aggregate Root (Company). Since a copy could quickly become outdated, it seems like you would only want a copy to exist while in memory and when saving the Contact, you would only save references to the Tasks.

Coming from a relational database background, how should I model relationships in db4o (or any object database)?

I'm experimenting with db4o as a data store, so to get to grips with it I thought I'd build myself a simple issue tracking web application (in ASP.NET MVC). I've found db4o to be excellent in terms of rapid development, especially for small apps like this, and it also negates the need for an ORM.
However, having come from a SQL Server/MySQL background I'm a little unsure of how I should be structuring my objects when it comes to relationships (or perhaps I just don't properly understand the way object databases work).
Here's my simple example: I have just two model classes, Issue and Person.
public class Issue
{
public string ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime? SubmittedOn { get; set; }
public DateTime? ResolvedOn { get; set; }
public Person AssignedBy { get; set; }
public Person AssignedTo { get; set; }
}
public class Person
{
public string ID { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string Password { get; set; }
}
The ID properties are just GUID strings generated by the .NET Guid.NewGuid() helper.
So here's how I initially thought the application would work; please ignore any security concerns etc and assume we already have a few Person objects stored in the database:
User logs in. Query the database for the Person which matches the username and password, and store his/her GUID id as a session variable. Redirect to app home screen.
Logged in user creates a new issue ticket, selecting the user to assign it to from a drop-down list. They fill in the other details (Title, Description etc), and then submit the form.
Query the Person objects in the database (by their GUID ID's) to get an object representing the logged in user and one representing the user the ticket has been assigned to. Create a new Person object (populated with the posted form data), assign the Person objects to the Issue object's AssignedBy and AssignedTo properties, and store it.
This would mean I have two Person objects stored against each Issue record. But what happens if I update the original Person—do all the stored references to that Person in the various issue objects update, or do I have to handle that manually? Are they references, or copies?
Would it be better/more efficient to just store a GUID string for the AssignedBy and AssignedTo fields (as below) and then look up the original person based on that each time?
public class Issue
{
public string ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime? SubmittedOn { get; set; }
public DateTime? ResolvedOn { get; set; }
public string AssignedByID { get; set; }
public string AssignedToID { get; set; }
}
I think I'm just stuck in a certain way of thinking which is confusing me. If someone could explain it clearly that would be most helpful!
Object-Databases try to provide the same semantics as objects in memory. The rule of thumb is: It works like objects in memory. Object databases store references between the objects in the database. When you update the object, that object is updates. And if you have a reference to that objects, you see the changed version.
In your case, the Issue-objects refer to the person object. When you update that person, all Issues which refer to it 'see' that update.
Of course, primitive types like int, strings, longs etc are handled like value objects and not a reference objects. Also arrays are handled like value objects in db4o, this means a array is stored together with the object and not as a reference. Everything else is stored as a reference, even collections like List or Dictionaries.
Please take a look at:
http://developer.db4o.com/Documentation/Reference/db4o-7.4/java/reference/html/reference/basic_concepts/database_models/object-relational_how_to.html
Best!

Resources