Xamarin Form Create Table Problem in SqLite based complex class - sqlite

I develop cross platform mobile app on Xamarin Forms.
I try to create tables in sqlite. My class name is 'News' and News class containts 'Country' class.
Create table code and class is like below.
[Serializable]
[DataContract]
public class News
{
[PrimaryKey]
[DataMember]
public int Id { get; set; }
[DataMember]
public Guid ActivityId { get; set; }
[DataMember]
public int Type { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public CountryBase Country { get; set; }
}
and code is something like
var db = new SQLiteConnection (dbPath);
db.CreateTable<News> ();
This isn't working. When i remove the country class it works.
I try to create country table separately but still i couldn't create News table. How can i fix the problem?

The SQLite doesn't allow relationships, and public CountryBase Country { get; set; } is interpreted as one.
So you need:
either to serialize your Country as a string before inserting, and you will have this:
[DataMember]
public string SerializedCountry { get; set; }
[Ignore]
public CountryBase Country { get; set; }
And you need to handle serialization with Json.net manually of the Country.
Or create another Country table, and specify its id in your entity definition:
[Serializable]
[DataContract]
public class News
{
[PrimaryKey]
[DataMember]
public int Id { get; set; }
[DataMember]
public Guid ActivityId { get; set; }
[DataMember]
public int Type { get; set; }
[DataMember]
public string Title { get; set; }
[DataMember]
public int CountryId { get; set; }
}
[Serializable]
[DataContract]
public class Country
{
[PrimaryKey]
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
...
}

Related

When creating a one-to-one relationship in an entity it throws an error The navigation property 'StudentModel' was not found on the dependent type

I want to create one to one relation between tables. My table is
public class StudentModel
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime DateOfBirth { get; set; }
[Required, Display(Name="Department Name")]
public int DeptId { get; set; }
//navigration proprty
[ForeignKey("DeptId")]
public virtual DepartmentModels Department { get; set; }
public virtual StudentRegistrationModels StudentRegistration { get; set; }
}
and my other table is
public class StudentRegistrationModels
{
[Key]
public int StudentId { get; set; }
[Required]
public int CourseId { get; set; }
[Required]
public DateTime EnrollDate { get; set; }
public bool IsPaymentComplete { get; set; }
//navigration proprty
[ForeignKey("StudentId")]
public virtual StudentModel Student { get; set; }
[ForeignKey("CourseId")]
public virtual CourseModels Course { get; set; }
//oneToOneStudentRegistration
}
But when I make migration it throws an error:
Unable to determine the principal end of an association between the types 'StudentManagementSystem.Models.StudentModel' and 'StudentManagementSystem.Models.StudentRegistrationModels'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
Why is this occurring?
I believe the issue is that you have a single StudentRegistrationModel instance in your StudentModel, where the StudentRegistrationModel looks to be more of a Many-to-Many structure. Can a single student only be registered to a single course? If that were the case it would make more sense for StudentModel to just have a CourseModel reference. Since a Student probably has multiple courses, it would probably make more sense for StudentModel to have:
public virtual ICollection<StudentRegistrationModels> StudentRegistration { get; set; } = new List<StudentRegistrationModels>();
Then ensuring that your model configuration maps out the relationship. This can be done with an attribute, as part of the DbContext OnModelCreating, or using an EntityTypeConfiguration. With Attributes:
[InverseProperty("Student")] // Tells EF this collection corresponds to the Student on the StudentRegistrationModel.
public virtual ICollection<StudentRegistrationModels> StudentRegistration { get; set; } = new List<StudentRegistrationModels>();
Maybe try to add [Key] annotation to Id field in StudentModel.
using System.ComponentModel.DataAnnotations;
public class StudentModel
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime DateOfBirth { get; set; }
[Required, Display(Name="Department Name")]
public int DeptId { get; set; }
//navigration proprty
[ForeignKey("DeptId")]
public virtual DepartmentModels Department { get; set; }
public virtual StudentRegistrationModels StudentRegistration { get; set; }
}
or if it won't work try map relationship in OnModelCreating in your data context.

Online Shop - Create an order with multiple products MVC .net

So I am building an online shop using Code-First MVC
So I created this model classes for now (don't take the types of the attributes too serious for now):
Products (Produto):
public Produto()
{
ListaProdutoEncomenda = new HashSet<Produto_Encomenda>();
}
public int ProdutoID { get; set; }
[Required]
[StringLength(50)]
public string Nome { get; set; }
[Required]
public double Preco { get; set; }
[Required]
public double Peso { get; set; }
[Required]
[StringLength(255)]
public string Descricao { get; set; }
[Required]
public double IVA { get; set; }
public string Imagem { get; set; }
public DateTime UltimaAtualizacao { get; set; }
public int Stock { get; set; }
public int CategoriaID {get;set;}
public virtual ICollection<Produto_Encomenda> ListaProdutoEncomenda { get; set; }
}
Encomenda (Order):
public class Encomenda
{
public Encomenda()
{
ListaProdutoEncomenda = new HashSet<Produto_Encomenda>();
}
[Key]
public int IDEncomenda { get; set; }
[Required]
public DateTime DataSubmissao { get; set; }
[Required]
public DateTime DataEnvio { get; set; }
[Required]
public int EstadoEnvioID { get; set; }
[StringLength(50)]
public string NomeDestino { get; set; }
[Required]
public int TipoExpedicaoID { get; set; }
[Required]
public int RegiaoDestinoID { get; set; }
[StringLength(50)]
public string MoradaDestino { get; set; }
[StringLength(50)]
public string CodPostalDestino { get; set; }
[Required]
[StringLength(50)]
public string MoradaFaturacao { get; set; }
[Required]
[StringLength(50)]
public string CodPostalFaturacao { get; set; }
public virtual ICollection<Produto_Encomenda> ListaProdutoEncomenda { get; set; }
}
And the connection table between the produtos (Products) and Encomenda (Order)
public class Produto_Encomenda
{
[Key]
public int IDProduto_Encomenda { get; set; }
[Required]
public string NomeProduto { get; set; }
[Required]
public int Quantidade { get; set; }
[Required]
public float preco { get; set; }
[Required]
public float IVA { get; set; }
public virtual Encomenda Encomenda { get; set; }
public virtual Produto Produto { get; set; }
[ForeignKey("Encomenda")]
public int IDEncomendaFK { get; set; }
[ForeignKey("Produto")]
public int IDProdutoFK { get; set; }
}
So my question is..
Let's pretend that a costumer buys 2 or 3 products or more.
How can I store all this products in a single line of an order?
Cheers and thanks a lot in advance for the time spent reading.
I'm not sure what you mean by "a single line of an order". Each product is a separate line item, and your entities already model this through the many-to-many relationship.
However, in general this setup is a very bad idea. Your order should not be directly related to products. Instead, your order should simply have an order item, and you'll create those order items based on the products that were sold. The reason for this is that products are very likely to change. If a product is removed because it's no longer available, for example, that doesn't negate the fact that it was previously sold in an order. However, in order for referential integrity to be maintained, any orders sold with that product would have to also have their relationship with that product removed. By having an entirely separate entity, i.e. order item, products can come and go, while the already created orders remain unaffected.
I guess you are looking to make a viewmodel
Create a class that contains Products and Encomenda class as property -
Model -
public class MyViewModel
{
public Produto Pinst{get;set;}
public Encomenda Einst{get;set;}
}
Controller or method-
public void SomeMethod()
{
List<MyViewModel> lst = new List<MyViewModel>();
//Now suppose
foreach(var items in listThatGetCreatedWithBuyerproductInfo)
{
MyViewModel obj = new MyViewModel ();
obj.Pinst = new Produto();
obj.Einst = new Encomenda();
//Here goes your properties from item in respected class instances
obj.Pinst.Nome = items.Nome;
obj.Einst.DataSubmissao = items.DataSubmissao;
//when you are done loading add obj to list
lst.Add(obj);
}
}
Hope it Helps if it does not tell me !!

Entity Framework Table Per Type inheritance with discriminator column

I am using EF5 TPT and thus don't expect a discriminator column. Why is it being created?
The ( simplified) table classes are;
[Table("SalesDocumentHeaders")]
public abstract class SalesDocumentHeader : LoggedEntity
{
[ForeignKey("CreatedByUserId")]
public virtual User CreatedBy { get; set; }
[Required]
public int CreatedByUserId { get; set; }
[Required]
public virtual DateTime? DocumentDate { get; set; }
[Required]
public String ReferenceNumber { get; set; }
}
[Table("SalesOrders")]
public class SalesOrder : SalesDocumentHeader
{
[Required]
public String CustomerOrderNumber { get; set; }
public DateTime? DeliverBy { get; set; }
public virtual SortableBindingList<SalesOrderLine> Lines { get; set; }
}
public abstract class LoggedEntity
{
public int Id { get; set; }
public Guid RowId { get; set; }
[ConcurrencyCheck]
public int RowVersionId { get; set; }
}
The context contains
public DbSet<SalesOrder> SalesOrders { get; set; }
public DbSet<SalesDocumentHeader> SalesDocumentHeaders { get; set; }
The SalesDocumentHeader table creates with a Discriminator column. What am I doing wrong?
it makes no difference whether SalesDocumentHeader is declared as abstract or not
because I had another class which inherited from SalesDocumentHeader which I forgot to mark with the table attribute

Allow null in model when using Code first

I have an model like this:
public class EquipmentEmployee
{
public int EquipmentEmployeeID { get; set; }
public int EmployeeID { get; set; }
public Employee Employee { get; set; }
public int EquipmentID { get; set; }
public Equipment Equipment { get; set; }
public int RequisitionID { get; set; }
public Requisition Requisition { get; set; }
public DateTime From { get; set; }
public DateTime To { get; set; }
public string Comment { get; set; }
}
I use Mvc scaffolding for creating my controllers, repositories and views. Int the create View I'm not able to POST since I dont have values for "to" and "RequisitionID". I have not added [Required] to them. Is this possible? To POST and have those two null?
You should declare optional fields using a nullable type
public int? RequisitionID { get; set; }
To accept the null values you can use the following solution.
public int? RequisitionID { get; set; }

EF5 Inheritance with code first

I've multiple smaller versions of classes that maps to single database table
e.g
UserBrief Class:
[Table("Users")]
public partial class UserBrief
{
[Key]
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
UserAdmin Class
[Table("Users")]
public partial class UserAdmin : UserBrief
{
public int RoleID { get; set; }
}
UserHR Class
[Table("Users")]
public partial class UserHR : UserBrief
{
public string EmailAddress { get; set; }
public string Phone { get; set; }
}
User Class
[Table("Users")]
public partial class User
{
[Key]
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int RoleID { get; set; }
public string EmailAddress { get; set; }
public string Phone { get; set; }
}
I've multiple bounded contexts. Depending on functionality of context I've used above classes.
If I add single class in context and Ignore all other classes then it works fine.
e.g
public DbSet<UserHR> UserHRs { get; set; }
protected override void OnModelCreating(System.Data.Entity.DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<UserBrief>();
modelBuilder.Ignore<UserAdmin >();
modelBuilder.Ignore<User>();
}
Now if I added UserBrief and UserHRs
It gives error "Invalid column name 'Discriminator'" as EF assumes that this is Table per Hierarchy (TPH) approach.
I've been searching for solution, but can't find how to do this.
Any ideas?
Thanks in advance.
The inherited classes in the POCO objects for the TPH approach should represent sub-types of the class, not just property sections. Having the User table which is a combination of UserHR and UserAdmin breaks this representation.
You could attempt to add a Discriminator property to the User table to fix the error, but I would suggest either just using the Users table with nullable properties or modeling your objects as 1-to-1 relationships:
public class UserBrief
{
[Key]
public int EmployeeID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual UserAdmin UserAdmin { get; set; }
public virtual UserHR UserHR { get; set; }
}
public class UserAdmin
{
[Key]
[ForeignKey("UserBrief")]
public int EmployeeID { get; set; }
public int RoleID { get; set; }
public virtual UserBrief UserBrief{ get; set; }
}
public class UserHR
{
[Key]
[ForeignKey("UserBrief")]
public int EmployeeID { get; set; }
public string EmailAddress { get; set; }
public string Phone { get; set; }
public virtual UserBrief UserBrief{ get; set; }
}

Resources