EF code first add model related exist childs - entity-framework

I try to add new model to DB but the model have child that already exists
and i got this error:
"A referential integrity constraint violation occurred: The property value(s) of 'Category.ID' on one end of a relationship do not match the property value(s) of 'Lesson.CategoryID' on the other end."
for example:
public class Category
{
public int ID { get; set; }
public string Name{ get; set; }
public List<Lesson> Lessons{ get; set; }
}
public class Lesson
{
public int ID { get; set; }
public string Name{ get; set; }
public List<Category> Categories { get; set; }
}
I think that the Category ID still 0 until the DB will generate new ID and Lesson.CategoryID filled in 0 that not exist in Categories
Save code:
DB.Categories.Add(obj);
DB.ChangeTracker.Entries()
.Where(x => x.Entity is BaseModel && x.State == EntityState.Added && ((BaseModel)x.Entity).ID > 0)
.ToList().ForEach(x => x.State = EntityState.Unchanged);
Any idea how to fix that?
Thanks anyway

Related

one-to-many relationship foreign key count

public class User
{
[Key]
public int id { get; set; } //PK
public string emailAddress { get; set; }
public List<Task> tasks { get; set; }
}
public class Task
{
[Key]
public int id { get; set; } //PK
public string name { get; set; }
//Navigation Properties
public User user{ get; set; }
public int userId { get; set; }
}
I've got two models above configured following the MSDN tutorial. So how can I properly get the number of tasks associated with a user?
I tried context.users.Where(u => u.emailAddress == email).FirstOrDefaultAsync().tasks.count; but it gives me a null pointer reference on the tasks object.
Then I tried context.tasks.Where(o=>o.user.emailAddress==email).Count() gives me correct number so it works
so I am wondering why the List is a null reference instead of a list with some elements in? thanks for the advice
Try the following query:
var cnt = context.users
.Where(u => u.emailAddress == email)
.Select(u => u.tasks.Count())
.FirstOrDefault();
You have to use LINQ extension Count() instead of List.Count
I think you are using entity framework with Eager loading (description). In that case you should call explicitly Include() method to load all user tasks. Example:
await (context.users.Where(u => u.emailAddress == email).Include(u => u.Tasks).FirstOrDefaultAsync()).Tasks.Count();
UPD: Not for the Production

How to delete only certain child entities in entity framework

I've searched and nothing I've come across works for this problem. I have child entities that all have a date completed field. When the parent entity is updated, I want to delete any child entities that don't have a value for the date completed field. Here's the code.
public int Save(ImmunizationForm form)
{
_context.Entry(form).State = EntityState.Detached;
//only clear our incomplete immunizations
var incompleteImmunizations = _context.ImmunizationFormImmunization.Where(x =>
x.ImmunizationFormId == form.Id && !x.DateCompleted.HasValue);
if (incompleteImmunizations.Any())
{
foreach (var i in incompleteImmunizations){
//_context.Entry(i).State = EntityState.Deleted;
_context.ImmunizationFormImmunization.Remove(i);
}
_context.SaveChanges(); //errors here
}
.....
}
My suspicion was that because I'm passing in an ImmunizationForm entity that has an Id value (meaning I'm not adding a new parent but updating), I would need to set the State to EntityState.Detached because further in my code I actually grab the entity to update from the database. But, that doesn't seem to help. As you can see I've tried both setting the State of the incompleteImmunization object to delete or just try to remove it. Neither are working. I keep getting the same error message...
The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.
Parent class
public class ImmunizationForm
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public ImmunizationForm()
{
ImmunizationFormImmunizations = new HashSet<ImmunizationFormImmunization>();
}
public int Id { get; set; }
public string Name { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<ImmunizationFormImmunization> ImmunizationFormImmunizations { get; set; }
}
Child class
public class ImmunizationFormImmunization
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public ImmunizationFormImmunization()
{
}
public int Id { get; set; }
[ForeignKey("ImmunizationForm")]
public int ImmunizationFormId { get; set; }
public short ImmunizationTypeId { get; set; }
public byte? GroupId { get; set; }
public byte DocumentationRequirement { get; set; }
public DateTime? DateCompleted { get; set; }
public string RejectionReason { get; set; }
public DateTime? RejectedDate { get; set; }
[Column(TypeName = "numeric")]
public decimal? RejectedBy { get; set; }
public virtual ImmunizationForm ImmunizationForm { get; set; }
public virtual TypeImmunization TypeImmunization { get; set; }
}

update foreign key using entity framework

i am trying to update foreign key in a table named(Friendship).The foreign key is of the table named(FriendshipStatus) the problem is that all the values are updated except the foreign key. I m using code first approach.
Friendship Class
public class Friendship
{
public int Id { get; set; }
public User UserOne { get; set; }
public User UserTwo { get; set; }
public FriendshipStatus Status { get; set; }
public User ReqSB { get; set; }
public RelationType RelationType { get; set; }
public Relationship Relationship { get; set; }
public DateTime FriendshipDate { get; set; }
}
FriendshipStatus class
public class FriendshipStatus
{
public int Id { get; set; }
public string Name { get; set; }
}
Here is the code for update
using (context)
{
Friendship f = getFrienshipRecord(u1, u2); // get single record from db which is to be updated
if (f != null)
{
Friendship ff = new Friendship();
ff.Status = new FriendshipStatus() { Id = 2}; //actually wants to update this this field
ff.Id = f.Id;
ff.FriendshipDate = DateTime.Now;
context.Entry(ff).State = EntityState.Modified;
context.SaveChanges();
}
}
The above code changes datetime but it does not change foreign key.
This is the technique I use for updates that include a child. First, I like to expose the Foreign Key as part of the parent. If you name it FriendshipStatusId, EF will make the association automatically or you can add an annotation or fluent code if preferred:
public class Friendship
{
public int Id { get; set; }
public User UserOne { get; set; }
public User UserTwo { get; set; }
public int? FriendshipStatusId { get; set; } // optional FK
public FriendshipStatus Status { get; set; }
public User ReqSB { get; set; }
public RelationType RelationType { get; set; }
public Relationship Relationship { get; set; }
public DateTime FriendshipDate { get; set; }
}
Now you can do your update by simply fetching the entity (which puts it under tracking) and updating the FK:
using (context)
{
Friendship f = getFrienshipRecord(u1, u2); // get single record from db which is to be updated
if (f != null)
{
f.FriendshipDate = DateTime.Now;
f.FriendshipStatusId = 2;
context.SaveChanges();
}
}
Note that if you add the FK you may need to do a migration or regenerate your database because the EF default might be something like FriendshipStatus_Id.

How to get rows of Data from Multiple Tables using LinQ To Entities

I am using dbcontext Code first to get a query base on this condition for the Classes (tables) below:
Creator != null && ArticleAttached != null && !IsCancelled
var ArticleStudentLiked = dbcontext.LearningActivites
.Where(la => la.Creator != null && la.ArticleAttached != null && !la.IsCancelled)
.Sum(la => la.ArticleAttached.StudentsLiked.Count);
var NewsArticleComment = dbcontext.LearningActivites
.Where(la => la.Creator != null && la.ArticleAttached != null && !la.IsCancelled)
.Sum(la => la.ArticleAttached.Comments.Count);
The following Methods only return count for:
ArticleStudentLiked
ArticleComment
I need to get rows of record from the Queries into a single collection which I can pass to View to display line by line
like this :
Article Title, No. of Likes, No. Of Comments
How to use LinQ to Get these : Article Title,No. Of Like , No. of Comment
Classes:
public class LearningActivity
{
public virtual ArticleCreator Creator { get; set; }
public virtual ArticleCreator EditedBy { get; set; }
public virtual Teacher CreatedByTeacher { get; set; }
public virtual Article ArticleAttached { get; set; }
public virtual Article ArticleAttachedByOther { get; set; }
public bool IsCancelled { get; set; }
}
public class Article
{
public string ArticleTitle {get;set;}
public virtual IList<Teacher> TeachersLiked { get; set; }
public virtual IList<Student> StudentsLiked { get; set; }
public virtual IList<ArticleComment> Comments { get; set; }
}
public class Student
{
public virtual IList<ArticleCommentStudent> Comments { get; set; }
}
Thanks
Can you try this
// LikeCount is total of Teacher and Student Likes
// and where clause can be added before Select
var result = dbcontext.Classes
.Select(x=> new { ArticleTitle = x.ArticleTitle,
LikeCount = x.TeachersLiked.Count() + x.StudentsLiked.Count(),
CommentCount= x.Comments.Count }).First();

Include after select not load navigation property in Entity Framework core

I use entity framework core 1.1.
I have a query like below, and I expect to users who have UserProfile by using Include, load UserProfile.
But this query always return UserProfile null .
Query:
var user = dbContext.UserMappers
.Where(e => e.OldUserId == id)
.Select(e => e.User)
.Include(e=>e.UserProfile)
.FirstOrDefault();
Models:
public class UserMapper
{
[Key, ForeignKey(nameof(User))]
public string UserId { get; set; }
public User User { get; set; }
public int OldUserId { get; set; }
}
public class User : IdentityUser
{
public bool Suspended { get; set; }
public string Nickname { get; set; }
public virtual UserProfile UserProfile { get; set; }
}
public class UserProfile
{
[Key, ForeignKey(nameof(User))]
public string UserId { get; set; }
public string Name { get; set; }
public string Family { get; set; }
public string Telephone { get; set; }
}
From the EF Core documentation - Loading Related Data - Ignored includes section (highlight is mine):
If you change the query so that it no longer returns instances of the entity type that the query began with, then the include operators are ignored.
This is different from EF6 where Include works on the final query entity type. I don't know if this is a current limitation or "by design", but for now you have to start your queries with the entity requiring includes.
In your case, it should be something like this:
var user = dbContext.Users
// if you don't have inverse navigation property
.Where(e => dbContext.UserMappers.Any(um => um.UserId == e.Id && um.OldUserId == id))
// if you have inverse collection navigation property
//.Where(e => e.UserMappers.Any(um.OldUserId == id))
// if you have inverse reference navigation property
//.Where(e => e.UserMapper.OldUserId == id)
.Include(e => e.UserProfile)
.FirstOrDefault();