SQLite.Net and SQLiteNetExtensions error after update - relationships and primary keys - sqlite-net-extensions

I've just updated all the SQLite nugget packages in my proj. All db operations were working just fine.
Now, when I try this:
items = db.GetAllWithChildren();
I get this error:
Item.ItemEvents: OneToMany relationship origin must have Primary Key
So nothing has changed in code and primary keys are GUIDs as strings
All entities inherit from a base class like this:
public class BusinessEntityBase : IBusinessEntity
{
public BusinessEntityBase()
{
Id = Guid.NewGuid().ToString();
}
[PrimaryKey]
public string Id { get; set; }
}
Does that error mean that I cannot/should not inherit from a base class which implements the Id property? Should each class implement it's own Id property?
I'm only asking as all these attributes/relationships are sorted out through reflection and something might have changed to negate how I've built my entity layer...
Not sure why I'm getting this now and not before updating all SQLite plugins...
Thx
SQLite Packages Installed

Found the issue for anyone who needs to know.
Entity attributes are ambiguous across the SQLite and SQLite.Net.Attributes namespaces.
The attributes need to be prefixed with the SQLite namespace, ie: [SQLite.PrimaryKey]
Hope that helps a few...

Related

Set a Primary Key for an Entity without ingaffect database

I'm working on an ASP.NET MVC project, I use Entity Framework (Database First), I created a data model depend on SQL server database, I created a Table in the database and I updated the data model from the database, and when I try to add a record to the new table I created (this table doesn't have a PK) I got an error, when I search about the error I Understood that in Entity Framework need to have a PK for Entity.
So I ASK if I can set a Primary Key for an Entity without affect database, or any other solution to solve this problem.
You can use partial Class for set Key and without effect Original Model and Database
// orginal class **Entity** `YourEntity.cs`
public class YourEntity
{
public int Id { get; set; }
}
Then create a new Class must name different ordinal class ex YourEntityMeta.cs it is physical name
// must change name ordinal class `YourEntity.cs` but add **partial** keyword
[MetadataType(typeof(Metadata))]
public partial class YourEntity
{
sealed class Metadata
{
[Key]
public int Id { get; set; }
}
}
Entity Framework always needs a primary key column with name id. Add a column (id) in the database table and set "Is Identity: true" for it. Then update the database model of your project.

.SaveChanges() stores duplicates in entity framework

for ( int i = 0; i < libraryList.Count; i++)
{
if (ModelState.IsValid)
{
context.Library.Add(libraryList[i]);
context.SaveChanges();
}
}
A library contains an entity 'predefinedgoals' which is already set up in the DB. So when the above code runs it stores dublicates of 'predefinedgoals' and assigns new ID's to them.
I read that I should attach the existing entity to the context but I'm not sure how to to do it in my scenario. The classes look like this:
class library
int libraryID
list<book> bks
.
class book
int bookID
list<importantdates> impdts
.
class importantdate
int importantdateID
predefinedgoal predfg
int numberofresellers
.
class predefinedgoal
int predefinedgoalID
string description
int daysfrompublication
I tried something like this right after ModelState.IsValid but I sense I'm doing it wrong:
var prdfgs= context.predefinedgoals.ToList();
foreach(var pg in prdfgs)
context.predefinedgoals.Attach(pg);
This answer is going to be based on a couple of assumptions, but I've seen this exact problem so many times that this is automatically my go-to answer.
What I think you're doing is that you're creating Library, Book, and ImportantDate objects (and setting up all of the relationships between them as well). In the process of doing all of this, however, you are trying to set the PreDefinedGoal navigational property on those ImportantDate objects, all the while leaving the actual int FK property (that would be something like PreDefinedGoalID), still set to 0. When that happens, Entity Framework disregards the fact that the object contained in the navigational property has an ID on it, and assumes that you are trying to create this PreDefinedGoal object from scratch, just like you're creating the ImportantDate object (as well as the others). It will then create a PreDefinedGoal object with the exact same data as the one you're actually trying to use, but it will create it as a separate, duplicate record in the database.
The solution to your problem then is simple: Don't set the navigational property. Just simply set the FK (ImportantDate.PreDefinedGoalID) to the ID of the PreDefinedGoal object that you want to hook up to it. When you do that, and you save it, Entity Framework will then reach out to the database for the correct object based on that ID, and thus you will avoid having duplicate PreDefinedGoal objects in your database.
FYI: I learned this from one of Julie Lerman's MSDN posts. If you're going to be working with EF, I highly recommend reading her posts and columns.
I am in the same situation and found a workaround. The way this workaround works makes me think that in this case EF is to blame for handling the situation badly.
In order to simplify the example I will just post an example with one object and it's navigational property.
public class Topic
{
int Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
}
public class Course
{
int Id { get; set; }
public Topic Topic { get; set; }
// additional properties don't matter now
}
Note the absence of any foreign key or other data annotations. EF6 will correctly create the database schema from this and infer that Id is the primary key.
Without workaround adding a new course for an existing topic will create a new topic object with a new Id (overwriting the Id it was given!) :
db.Courses.Add(course);
await db.SaveChangesAsync();
The braindead workaround:
course.topic = db.Topics.Find(course.topic.Id);
db.Courses.Add(course);
await db.SaveChangesAsync();
In other words, if the topic has been loaded from the context directly, EF will recognize it as an existing topic and don't try to add it again.
Update: To just attach the entity without reloading it:
db.Topics.Attach(course.topic);
However you will run into more issues with this setup, it is probably best to use ForeignKey attribute(s) and include the TopicId in Course object. Following works OK but still looks ridiculous to me:
[ForeignKey("Topic")]
public int TopicId { get; set; }
[ForeignKey("TopicId")]
public virtual Topic Topic { get; set; }
Would love to hear about a less redundant solution though.
The answer to why it stored duplicates in my scenario was that I performed tasks in two different classes - using different database context variables in each of them.
So class #1 is the one in my question, that's where I'm saving to the DB using context #1. In class #2 I retrieved all the PredefinedGoals and added them to ImportantDates but to do this I created context #2. The ID's and objects were the same but retrieved from different context variables.
I solved it by retrieving the PredefinedGoals in class #1 with context variable #1 and sent them as an argument to class #2.

MVC 5 Scaffolding with inheritance uses the wrong entity set

With MVC 5 and EF 6.1 I am using a simple inheritance hierarchy, where class Student inherits from class Person. For both classes I have an entity set (DbSet property) in my database context:
public class DatabaseContext : DbContext
{
public DbSet<Person> Persons { get; set; }
public DbSet<Student> Students { get; set; }
}
Now when I ask the scaffolder to generate a controller for Student, the subclass, it uses the Persons entity set, leading to statements such as
Student student = db.Persons.Find(id);
where the compiler obviously complains that it cannot just convert any Person to a Student.
Is there a way to make sure that the scaffolder uses the correct entity set (Students in this case)?
Note that removing the Persons entity set is not a good solution, because there are other controllers that need that.
Use find and replace to change all occurrences in the Controller class of the parent DBSet to the child DBSet eg change Persons to Students.
As you probably know (as I think you raised it) Microsoft have confirmed this is a known bug http://connect.microsoft.com/VisualStudio/feedbackdetail/view/945937/mvc-5-scaffolding-with-inheritance-uses-the-wrong-entity-set but they won't be fixing it.
Instead of inheritance why not use a relationship making personID the Foreign key ? That why you can db.students.find(personID)
And
db.person.find(personID)
To find all details ?
Extra code but I can't think of another way
You can use the command OfType<>, as shown:
Student student = db.Persons.OfType<Student>().SingleOrDefault(s => s.id == id);
This command works with inheritance. In this case, when Student inherits from Person.

Entity Framework Code First : One-To-One association using Annotations

I am having .NET MVC 5 and Identity...
I am trying to get a one to one relationship for my Member class to my MemberInfo class..
So, My classes looks something like this:
IdentityUser is in the Microsoft.AspNet.Identity.EntityFramework namespace with string Id as its ID.
public class GRNUser : IdentityUser {
....
....
}
public class MemberUser : GRNUser {
public virtual Member MemberInfo {get; set; }
}
public class Member {
public int ID {get; set; }
public string MemberUserID {get; set; }
public virtual MemberUser MemberUser { get; set; }
}
In my Context, I have this
modelBuilder.Entity<Member>().HasRequired(m => m.MemberUser)
.WithOptional(u => u.MemberInfo);
So, the MemberUser and Member should be able to navigate to and from each other using the MemberUser's ID property and Member's MemberUserID property.
However, when my Database is created, it has an additional column "MemberUser_Id" instead of using my MemberUserID that I specified. How do I make it use "MemberUserID" that I specified?
I've tried using a few combination so of the ForiegnKey Data Annotation, but keeps on getting this error:
Member_MemberUser_Source: : Multiplicity is not valid in Role 'Member_MemberUser_Source' in relationship 'Member_MemberUser'. Because the Dependent Role properties are not the key properties, the upper bound of the multiplicity of the Dependent Role must be '*'.
I don't know whether i understood you right or not, but i'l do my best to help.
(I'l assume that you work with code first migration)
If you want to make a one-to-one relation, why not try to make a standalone entity for your info which will have a foreign key for the user entity and that foreign key will be annotated as the primary key of the entity?
Another way is why just not add whatever attributes you like to the Application User entity and work with it?
In any case i might have misunderstood your purpose, so please feel free to explain further since your post is a bit confusing.

Adding validation messages to MVC classes generated by Entity Framework

I am starting an MVC project and designing my DB in EF, which means I design the tables, and VS creates the classes I need to access them.
The problem is, I want to make use of attributes like DisplayName, Required and generating validation error messages ( including specifying rules to validate ).
As far as I can see, the classes are recreated every time I change my DB, so I can't really add them to the classes. Is there another way to do this once and have it persist ?
So you would use the MetadataType attribute and link your entity to a type where you'll set the validation attributes.
Something like this for an Entity Person:
[MetadataType(typeof(Person_Validation))]//<<link to metadata class
public partial class Person//<<<Your real entity class
{//this is in a separate file.
//note =>partial. There's nothing in this class
}
public class Person_Validation//the validations go here.
{
[StringLength(255, ErrorMessage="Name is required"), Required]
[DisplayName("Name")]
public string Name { get; set; }
}

Resources