SQLite net Extension one to many relationship Windows Phone - sqlite-net-extensions

I'm using sqlite net extension to create one to many relationship for 2 tables that am using there are tables in my C# code i follow tutorial in official site https://bitbucket.org/twincoders/sqlite-net-extensions
[Table("Stock")]
public class Stock
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[MaxLength(8)]
public string Symbol { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)] // One to many relationship with Valuation
public List<Valuation> Valuations { get; set; }
}
[Table("Valuation")]
public class Valuation
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[ForeignKey(typeof(Stock))] // Specify the foreign key
public int StockId { get; set; }
public DateTime Time { get; set; }
public decimal Price { get; set; }
}
Here is my code to create Stockobject and insert it to Db
var valuation = new List<Valuation>();
valuation.Add(new Valuation { Price = 1 });
var stock = new Stock();
stock.Valuations = valuation;
db.InsertWithChildren(stock);
but when i debug code and read stock data from db it shows me null for list of valuation what is problem here ?
That'is how it shows to me

You have to use db.GetWithChildren<Stock>() instead of db.Table<Stock>().
Example from twincoders:
// Get the object and the relationships
var storedValuation = db.GetWithChildren<Valuation>(valuation.Id);

Related

How to make a ViewModel for an anonymous type from a linq query

I have joined and grouped 2 databases using linq in my controller, and now I need to parse it to the view. I know, I gonna need a ViewModel to do it, but I have no clue what to put in it, to make it work.
My Linq query in the controller looks like this:
var energyUsageViewModel =
from e in applicationDbContext
join u in _context.UsagesPerMonth on e.Id equals u.EnergyUsageId into u2
group u2 by new { Year = e.Year }
into u3
select u3.ToList();
return View(energyUsageViewModel);
In short what the linq query does is taking the "year" from table "e" joining it with table "u" which contains the energy usage per month, which I am gonna use to make a table in my view, which displays the year and usage per month in one row.
And currently my ViewModel looks like this (obviously not working):
public class EnergyUsageViewModel
{
public IEnumerable<UsagePerMonth> UsagePerMonthVm { get; set; }
}
The view takes a model of:
#model IEnumerable<Jullerup.Models.EnergyUsageViewModel>
I have tried to modify the ViewModel to take u3, but haven't succeeded.
I get the following invalid operation exception:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Linq.Enumerable+SelectEnumerableIterator2[System.Linq.IGrouping2[<>f__AnonymousType101[System.String],System.Collections.Generic.IEnumerable1[Jullerup.Models.UsagePerMonth]],System.Collections.Generic.List1[System.Collections.Generic.IEnumerable1[Jullerup.Models.UsagePerMonth]]]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable`1[Jullerup.Models.EnergyUsageViewModel]'.
How do I edit my ViewModel to handle u3?
Update:
I'm working with 3 classes.
Customer class:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
//Navigation Prop
public ICollection<EnergyUsage>? energyUsage { get; set; }
}
EnergyUsage class:
public class EnergyUsage
{
public int Id { get; set; }
public int CustomerID { get; set; }
public DateTime Date { get; set; }
public int YearlyHeatUsage { get; private set; }
public List<UsagePerMonth> UsagePerYear { get; set; }
//Navigation Prop
public Customer? Customer { get; set; }
}
UsagePerMonth class:
public class UsagePerMonth
{
public int Id { get; set; }
public MonthEnum Month { get; set; }
public int Usage { get; set; }
public int HeatUsage { get; private set; }
public string EnergyType { get; set; }
private EnergyMeasurement energyType { get; set; }
public int EnergyUsageId { get; set; }
}
In the database Customer.Id (PK) has a one to many relationship to EnergyUsage.CustomerId (FK) and EnergyUsage.Id (PK) has a one to many relationship to UsagePerMonth.EnergyUsageId (FK).
What I am trying to do, is to get an object/list something I can use in the view to display all instances of UsagePerMonth grouped by Customer.Year for a certain Customer.Id.

Unable to add data into Many-To-Many relationship database table with code first

I have 3 tables that are connected together as follows:
Survey
public enum Language
{
Danish,
English
}
public class Survey
{
public Survey()
{
Id = Guid.NewGuid();
DateCreated = DateTime.Now;
Sort = 0;
}
[Key]
public Guid Id { get; set; }
public bool Active { get; set; }
public string Title { get; set; }
public bool Status { get; set; }
[Display(Name = "Kommentar")]
public string Comment { get; set; }
public string MAilReciever { get; set; }
public string CCMailReciever { get; set; }
public string BBCMailReciever { get; set; }
public int Sort { get; set; }
public DateTime DateCreated { get; set; }
public string StartText { get; set; }
public string EndText { get; set; }
public string RegardText { get; set; }
public Language Language { get; set; }
public virtual ICollection<UserSurvey> UserSurveys { get; set; }
public virtual ICollection<Chapters> Chapters { get; set; }
public virtual ICollection<Questions> Questions { get; set; }
}
ApplicationUser
The default ApplicationUser table from Mvc with identity.
UserSurvey (My relationShipTable between Survey and ApplicationUser)
public class UserSurvey
{
[Key, Column(Order = 0)]
public Guid SurveyId { get; set; }
[Key, Column(Order = 1)]
public string ApplicationUserId { get; set; }
public virtual Survey Survey { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
public bool Active { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public string RegardText { get; set; }
}
I'm trying to add a new relation between a user and a servey by the following code:
UserSurvey Item = new UserSurvey();
Item.Survey = s;
Item.ApplicationUser = userinfo;
Item.Active = true;
Item.StartDate = Convert.ToDateTime(dateFrom);
Item.EndDate = Convert.ToDateTime(dateTo);
db.UserSurvey.Add(Item);
db.SaveChanges();
The error message I get says that I cant "Duplicate the SurveyId primary key because it already exist in the database (table survey).
I know it exist but I just want to make a relation between users and surveys, not create a new survey or user.
Thanks for your help
Your problem is that you are providing a completed UserSurvey object with nested objects (Survey/ApplicationUser) populated. When you do that and set the changeset as "Add" (caused by db.UserSurvey.Add(Item);). EF will attempt to issue INSERT INTO for the parent (UserSurvey) and all child/related(Survey/ApplicationUser) tables since it thinks that the "Add" changeset applies to all of these tables. To resolve your issue, you need to just provide the Ids. That will just insert a new relationship:
UserSurvey Item = new UserSurvey();
//Item.Survey = s; //This object filling is making EF believe that you are attempting to add a new record in Survey. Comment it out
//Item.ApplicationUser = userinfo; //This object filling is making EF believe that you are attempting to add a new record in ApplicationUser. Comment it out
Item.ApplicationUserId = userinfo.ApplicationUserId;//or whatever is the id column name in ApplicationUser table/class
Item.SurveyId = s.SurveyId;//I see that you are missing SurveyId property in UserSurvey. You will need to add this. This will be the Foreign Key to Survey table just like you have ApplicationUserId FK to ApplicationUser table.
Item.Active = true;
Item.StartDate = Convert.ToDateTime(dateFrom);
Item.EndDate = Convert.ToDateTime(dateTo);
db.UserSurvey.Add(Item);
db.SaveChanges();
So, the underlying idea is to fill the Ids if the nested records (Survey/Application in this case) already exist. You only populated nested object when you want EF to attempt to INSERT them too for you. Dont populate them if you dont want this. Just the Ids help EF to create just the relationship and not go after creating these related records again for you.
Hope this helps.

Update many-to-many relationship efficiently

I've 2 model classes.
public class Candidate
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Skill> Skills { get; set; }
}
public class Skill
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Candidate> Candidates { get; set; }
}
This creates me 3 tables.
Candidates
Id Name
1 Tom
2 John
Skills
Id Name
1 C#
2 MVC
3 SQL
4 nHibernate
5 Java
I've made the association in the AUTOGENERATED table :
CandidateSkills
CandidateId SkillId
1 2
1 3
Now I've want to update the skills for candidateId 1 i.e. Tom who wants to remove his SkillId : 2 i.e. MVC and add new SkillId : 4 & 5 i.e. nHibernate & Java respectively.
I get the set of Ids from the form i.e. 3, 4 & 5 & and the candidate Id : 1 , Since 2 is removed by the user.
My API is like this :
public Candidate Add(int candidateId, int[] skillIds)
{
var model = dbContext.candidate.Find(candidateId);
}
How do I update the candidate record in an efficient way, making the least database calls?
With many-to-many associations in Entity Framework you can only work with objects, not with primitive Id values.
public void Add(int candidateId, int[] skillIds)
{
var model = dbContext.candidate.Include(c => c.Skills)
.Single(candidateId => c.candidateId == candidateId);
var skills = dbContext.Skills.Where(s => skillIds.Contains(s.Id)).ToArray();
foreach (var skill in skills)
{
model.Skills.Add(skill);
}
dbContext.SaveChanges();
}
You must fetch the candidate with its skills loaded, hence the Include. The skills must be loaded for EF to be able to track changes to the collection.
If it's really a great deal for you to optimize performance you must create a junction class CandidateSkill class in your model, so you can add/delete associations without loading candidate or skill objects.
public class CandidateToSkill
{
public Candidate Candidate{ get; set; }
[Key,Column(Order = 0)]
public int CandidateID { get; set; }
[Key,Column(Order = 1)]
public int SkillID{ get; set; }
public Skill Skill { get; set; }
}
You need also add this class as DbSet in your dbContext class
public class Candidate
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<CandidateToSkill> CandidateSkills{ get; set; }
}
public class Skill
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<CandidateToSkill> SkillCandidates{ get; set; }
}
and the controller code
public void Add(int candidateId, int[] skillIds)
{
using (var db = new YourdbContext())
{
foreach (int skillID in skillIds )
{
db.CandidateToSkill.Add(new CandidateToSkill(){skillID,candidateId});
}
db.SaveChanges();
}
}
in this sample u have only marking a candidates to add to our context (in your Link-table) and Adding em to db with db.SaveChanges()
You could just mark the entity state as modified and save the context.
public void UpdateCandidate(Candidate candidate)
{
Context.Entry(candidate).State = EntityState.Modified;
}

Entity framework Entities in 'xxContext.x' participate in the 'x_y' relationship error

Before me, one developer used Entity Framework code first. I am not good at EF code first, so when I try to insert data, my code gives this error:
Entities in 'TourismContext.HotelOrders' participate in the 'HotelOrder_Order' relationship. 0 related 'HotelOrder_Order_Target' were found. 1 'HotelOrder_Order_Target' is expected.
This is my insert code:
var hotelOrdersInsert = new Data.Entities.HotelOrder
{
OrderId = odr.ID // this gives 7
HotelID = 13,
StartAt = DateTime.Now, // arrivalDate,
EndAt = DateTime.Now, // departureDate,
PaymentTypeID = 1,
PaymentStatusID = 1,
PaymentIdentifier = "a",
TotalRate = Convert.ToDecimal(total),
CurrencyID = 1
};
db.HotelOrders.Add(hotelOrdersInsert);
db.SaveChanges();
And this is my HotelOrder class:
public class HotelOrder
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Required]
public int HotelID { get; set; }
public int OrderId { get; set; }
// other properties
public virtual Order Order { get; set; }
public virtual Hotel Hotel { get; set; }
}
This is my Order class:
public class Order
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public virtual HotelOrder HotelOrder { get; set; }
}
Where can I find the relationship between the order and hotel order models?
You must write this relation as follows:
public class HotelOrder
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[Required]
public int HotelID { get; set; }
[ForeignKey("Order")]
public int OrderId { get; set; }
public Order Order { get; set; }
[ForeignKey("Hotel")]
public int HotelId { get; set; }
public Hotel Hotel { get; set; }
}
public class Order
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public List<HotelOrder> HotelOrders { get; set; }
}
The problem is the relationship between HotelOrder and Order. It's most likely that you have a 1 to 1 relation. Meaning, Every HotelOrder must have an Order.
The relation is probably defined in the so called fluent API. Check the OnModelCreating(DbModelBuilder) function override of your class derived from DbContext. It probably states something like this:
modelBuilder.Entity<HotelOrder>().HasRequired(hotel_order => hotel_order.Order).WithRequiredPrincipal();
This tells EntityFramework that every HotelOrder must have an Order.
Alternatively, the relationship could be defined as DataAnnotations. Like Elvin Mammadov explained in his answer.
At this point the solution becomes obvious. You need to add an instance of Order to your HotelOrder instance before adding it to db.HotelOrders.

Attribute of LINQ result is NULL but relationship is working

I have set up 3 models, code first and the relationships seem to be working but one is causing me a problem.
I have Article, Language and Edition Classes
public class Article
{
public int ID { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
}
public class Language
{
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
public class Edition
{
public int ID { get; set; }
public Article Article { get; set; }
public Language Language { get; set; }
public string Title { get; set; }
public string Details { get; set; }
}
In my bootstrap/DBinitialiser, I can create Objects and populate them fine. The DB is created and the foreign keys for Language and Article are both present on the Edition table and correctly entered.
var engLang = new Language() {Code="en", Name="English Language"};
var altLang = new Language() {Code="xx", Name="Alternative Language"};
db.Languages.Add(engLang);
db.Languages.Add(altLang);
db.SaveChanges();
var testArt = new Article() { Name = "test" };
db.Articles.Add(testArt);
db.SaveChanges();
db.Editions.Add(new Edition(){Article = testArt, Language = engLang, Title="English Content"});
db.Editions.Add(new Edition(){Article = testArt, Language = altLang, Title="Alternative Content"});
db.SaveChanges();
I can now query the Editions and return a list of them, but the Language attribute is always NULL. The Article Attribute works fine.
var query = db.Editions.Where(r => r.Article.ID == Article.ID);
foreach (Edition item in query)
{
// item.Language => NULL
// item.Article => {Object Article}
}
I'm new to .net and Entity-Framework and can't work out why I always get this error.
I can even query by r => r.Language.ID == 1 and still get a NULL attribute on the Edition object.
Make sure you are using EF codefirst in right manner. Here you have some ambiguities. You must determine what relationships actually should exist, in your POCOs. Change classes like bellow:
public class Article
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
}
public class Language
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
public class Edition
{
[Key]
public int ID { get; set; }
public virtual Article Article { get; set; }
public virtual Language Language { get; set; }
public string Title { get; set; }
public string Details { get; set; }
}
With thanks to AmirHossein Mehrvarzi for helping me write my models more clearly, I believe this error to be caused by the lazy loading of entities while iterating through the result of the query. ref: Entity Framework: There is already an open DataReader associated with this Command.
Without enabling MultipleActiveResultSets I simply added an Include statement to my linq
var query = db.Editions.Where(r => r.Article.ID == Article.ID).Include(r => r.Language);
foreach (Edition item in query)
{
// item.Language => {Object Language}
// item.Article => {Object Article}
}

Resources