Xamarin Forms Add List to SQL database - sqlite

I have a problem. I created the following class:
public class KnownDevice
{
public int Id { get; set; }
public string Name { get; set; }
public string IP { get; set; }
public string MAC { get; set; }
public string Type { get; set; }
public List<TriangleRegistryObject> triangles { get; set; }
public List<HexagonRegistryObject> hexagons { get; set; }
}
Now, I want to create a Database on the mobile phone itself, so I use the following code to create the table:
database = DependencyService.Get<ISQLite>().GetConnection();
database.CreateTable<KnownDevice>();
But the code crashes on the second line with the error:
System.NotSupportedException: 'Don't know about
System.Collections.Generic.List`1
Now on the internet I found that it is not allowed to add a List to a database, but I need the data in that list, so I have no idea how I can fix this problem. The list can contain arround 25 rows!
Any idea how I can solve this problem?

List<TriangleRegistryObject> is not a valid type for a SQLite database value. Your type of List<TriangleRegistryObject> does not match any of the clrType == typeof(XXXX) statements, so you get that exception. You will need to rethink the class structure a little to be able to use SQLite-net like that.
For more details about the SQLite database, you could download the source file from the link for reference.
https://learn.microsoft.com/zh-cn/samples/xamarin/xamarin-forms-samples/todo/
If you want to use ou could use List, you could use SQLite-Net Extensions instead of SQLite.
You could refer to the link. The SQLite-Net Extensions library direct to specific relationships in database.
How can you store lists of objects in SQLite.net?

Related

SQLite.net database with Xamarin.Forms App

I have a problem with an SQLite database in my Xamarin.Forms PCL project.
I have followed this example from Microsoft Docs:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/databases
I've been using my own types to store data and it's worked Ok for simple custom types, but I've recently added List<int> and Attendance type to the custom object (Info).
Now when I try and create the object, i get the following errors:
Don't know about System.Collections.Generic.List`1[System.Int32]
Don't know about MyApp.Attendance
Here is the init code:
readonly SQLiteAsyncConnection database;
database = new SQLiteAsyncConnection(dbPath);
database.CreateTableAsync<UserPrefrences>().Wait();
database.CreateTableAsync<Attendance>().Wait();
database.CreateTableAsync<Info>().Wait();
I'm using Xamarin.Forms with Xamarin.iOS.
You can not store them by default like that. However there is sqlite-net-extensions which you can use to accomplish that. You can take a look about sqlite-net-extensions here.
Using this extension you will be able to do that with TextBlob property, something like this:
public class Address
{
public string StreetName { get; set; }
public string Number { get; set; }
public string PostalCode { get; set; }
public string Country { get; set; }
}
public class Person
{
public string Name { get; set; }
[TextBlob("PhonesBlobbed")]
public List<string> PhoneNumbers { get; set; }
[TextBlob("AddressesBlobbed")]
public List<Address> Addresses { get; set; }
public string PhonesBlobbed { get; set; } // serialized phone numbers
public string AddressesBlobbed { get; set; } // serialized addresses
}
More explanation about TextBlob from url.
Text blobbed properties Text-blobbed properties are serialized into a text property when saved and deserialized when loaded. This allows
storing simple objects in the same table in a single column.
Text-blobbed properties have a small overhead of serializing and
deserializing the objects and some limitations, but are the best way
to store simple objects like List or Dictionary of basic types or
simple relationships.
Text-blobbed properties require a declared string property where the
serialized object is stored.
I just saw that there is also similar/same questions about this topic on StackOverflow already, so you can take a look at them also.
How can you store lists of objects in SQLite.net?
Can I use a List of String in a class intended for SQLite?

Azure DocumentDb id

I was playing with the azure Document Db and came accross a problem or rather confusing about Ids. I know that DocumentDb generates a "lowercase" "id" property for every document, this is fine with me, but I cant seem to figure out how to get this "id" when using the .net client. my code looks like below
public class Company
{
public Guid Id { get; set; } // this somehow does not get mapped to the "id" in the document.
public string Name { get; set; }
public string Address { get; set; }
}
so when i query like
client.CreateDocumentQuery<Company>(collection.DocumentsLink).ToList();
the id property is not mapped. I think I havent understood the ID concept in document db and how it maps to your entities properly.
Any help is much appreciated.
Try changing your company entity to
[JsonProperty("id")]
public String Id { get; set; }
This will load the documentdb generated Id, into the id field.
Let me know if that doesnt work.

EF Code First: One-to-One One-way Relationship

I regularly have the following structure:
MyClass
public virtual ICollection<Version> Versions { get; set; }
public virtual Version CurrentVersion { get; set; }
That is, there is a list of stuff, and some class both points to that list, and one specific item in that list - either the current version of many versions, the next upcoming event in a list of events, etc.
In my schema what I'd like to end up with is a Foreign Key pointing from Version to MyClass - that much works out properly. But then I'd like a Foreign Key pointing from MyClass to Version representing the CurrentVersion property, with no Foreign Key pointing back - I don't want the extra storage or bother of telling a Version what MyClass it's the CurrentVersion for, if any. Put another way, I'd like this second relationship to be one-way from MyClass to Version, even though it's one-to-one.
What EF Code First gives me instead is the normal one-to-many on the first property, with the FK from Version to MyClass, but then a full one-to-one relationship on the second property with an FK pointing in both directions - so the underlying schema for Version ends up with MyClass_Id and MyClass_Id1.
So, is there a way to get a one-way relationship in EF Code First without resorting to the Fluent API? It looked like maybe System.ComponentModel.DataAnnotations.Schema.InverseProperty had a shot at it, but it didn't seem to offer a way to say "Don't generate one."
The key is to specify the InverseProperty on the property that points back, so that EF realizes it's to the Many-to-Many, not to the One-to-One.
public class MyClass
{
public int Id { get; set; }
public Version CurrentVersion { get; set; }
public ICollection<Version> Versions { get; set; }
}
public class Version
{
public int Id { get; set; }
[InverseProperty("Versions")]
public Versioned Versioned { get; set; }
}

How can I name my Database using EF Code First?

I've got my EF Code First working exactly as expected aside from one small bit. I'm not sure how to name my Database File.
I'm using SQL CE, but I'm sure this applies to all forms of EF Code First.
Here's my DbContext
namespace MyApp.Domain.EntityFramework
{
public class DataContext : DbContext
{
//...
}
}
And when the database is created it's created as
MyApp.Domain.EntityFramework.DataContext.sdf
I'd prefer to just have it named
MyApp.sdf
Now I'm sure this is simple, but my Googling skills keep turning up examples where the database name is auto generated like mine.
http://www.hanselman.com/blog/SimpleCodeFirstWithEntityFramework4MagicUnicornFeatureCTP4.aspx
You need to specify a connection string (for example by creating a connection string named DataContext (your class name) in your config file, and set the desired name there.
I was looking to do the same. Managed to end up with this:
public class ShopDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Feature> Features { get; set; }
public DbSet<Category> Categories { get; set; }
public DbSet<Subcategory> Subcategories { get; set; }
public DbSet<Information> OrderInformation { get; set; }
public ShopDbContext() : base("Shop")
{
}
}
It will name your database "Shop" so just replace what is in the base("Shop") with whatever you want to call your database. Hope this helps.

Entity Framework 4.1 Code First: Advice on persisting data from external source?

Part of my project is to persist data from another source. In this case we have an SAP data source that we will need to pull data from. I need to take the data from SAP and map it to entities I have in my application. Here is an example of an entity I have in my application:
public class Project : BaseEntity
{
public string Name { get; set; }
public string ProjectNumber { get; set; }
public string Description { get; set; }
public string CreatedBy { get; set; }
public string ModifiedBy { get; set; }
public string Currency { get; set; }
#region Navigation Properties
public virtual Address Address { get; set; }
public virtual CompanyCode CompanyCode { get; set; }
public virtual ICollection<Contact> TeamMembers { get; set; }
#endregion
}
As you can see, I have child objects that I map from SAP as well. I need some advice on the best way to insert and update my entities. I am struggling with knowing when to add (insert) entities to my context and when to attach (update) them, because SAP doesn't have knowledge of what my application may or may not have. I need to guard against duplicates, too. For example, should I perform a lookup of each child entity in my parent entity to see if they exist before I apply them to the parent? Then, add / attach the entire parent object to the context or handle each entity separately while still maintaing their relationships?
Yes you must manually test everything to make correct decision what must be inserted, updated or deleted. Depending on the application you can use some more complex queries to reduce number of round trips to the database - for example you can use single query with Contains to load all TeamMembers needed for processed Project or you can load Project with including all related data if you also need to test if project exists.
I did large synchronization application before and I end up with pre-loading all entities at the beginning with few queries and working completely in memory.
Don't forget to use DbSet's Local property or Find method to take advantage of already loaded entities.
You can also use some custom stored procedures to improve performance of this operation.

Resources