one to zero or one Entityframework navigation property null - c#

I have an context with one to zero or one relationship in entity Framework.
but when i load my entity it will not load the related entity. It allways be null.
Here is my classes:
public class Timerow
{
[Key]
public int Id { get; set; }
[Required]
public int BestNo { get; set; }
[Required]
public int PosNo { get; set; }
[Required]
public int EmpNo { get; set; }
public virtual TimerowOvertime TimerowOvertimes { get; set; }
}
public class TimerowOvertime
{
[Key]
[ForeignKey("Timerow")]
public int Id { get; set; }
[Required]
public float Hours { get; set; }
public DateTime? Transfered { get; set; }
public bool Weekend { get; set; }
public bool ATF { get; set; }
[Required]
public virtual Timerow Timerow { get; set; }
}
But when i try to select Timerow and the related timerowOvertimes, timerowOvertimes allways be null.
i try this:
var timeRows = db.Timerows.ToList();
foreach (var timeRow in timeRows)
{
TimeSheet modelRow = new TimeSheet
{
Id = timeRow.Id,
Date = timeRow.Date,
BestNo = timeRow.BestNo,
PosNo = timeRow.PosNo,
Comment = timeRow.Comment,
Hours = timeRow.Hours,
Ready = timeRow.Ready,
SkillsNoId = timeRow.SkillsNoId
};
if(timeRow.TimerowOvertimes == null)
{
modelRow.ATF = false;
modelRow.Weekend = false;
modelRow.Overtime = 0;
}
else
{
modelRow.Overtime = timeRow.TimerowOvertimes.Hours;
modelRow.ATF = timeRow.TimerowOvertimes.ATF;
modelRow.Weekend = timeRow.TimerowOvertimes.Weekend;
}
}
Anyone has any idea about this?

You shouldn't have the Id property in TimerowOvertime annotated both as [Key] and [ForeignKey]. Currently it looks to bind the Timerow by using the primary key of TimerowOvertime entity. So you need to extend the TimerowOverTime entity to contain TimerowId property and annotate it with the [ForeignKey] attribute.
[ForeignKey("Timerow")]
public int TimerowId { get; set; }

Related

EF Code first, table relationship problem

I get an error in the comments model in relations, I'm waiting for a practical answer, it seems like there is nothing difficult. I use the picture model easily in the article model. I thought of using this table in the auhor model, but I am stuck in relationships, what should I do?
public class Article
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Detail { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public bool IsActive { get; set; } = false;
// Scaler properties
public int AuthorId { get; set; }
public int CategoryId { get; set; }
// Navigation properties
public virtual Picture Picture { get; set; } = new Picture();
public virtual Author Author { get; set; } = new Author();
public virtual Category Category { get; set; } = new Category();
public virtual ICollection<Comment>? Comments { get; set; }
}
public class Author
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string Surname { get; set; } = string.Empty;
public string EMail { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public DateTime DateOfBirth { get; set; }
public DateTime CreatedAt { get; set; }
// Navigation properties
public virtual ICollection<Article>? Articles { get; set; }
public virtual ICollection<Comment>? Comments { get; set; }
}
public class Category
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public byte SortBy { get; set; }
// Navigation property
public virtual ICollection<Article>? Articles { get; set; }
}
public class Comment
{
public int Id { get; set; }
public string Content { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
public bool IsActive { get; set; } = false;
// Scaler properties
public int ArticleId { get; set; }
public int AuthorId { get; set; }
// Navigation properties
public virtual Article Article { get; set; } = new Article();
public virtual Author Author { get; set; } = new Author();
}
public class Picture
{
public int Id { get; set; }
public string Src { get; set; } = string.Empty;
public string Alt { get; set; } = string.Empty;
public string? Title { get; set; }
// Scaler property
public int ArticleId { get; set; }
// Navigation property
public virtual Article Article { get; set; } = new Article();
}
This is the error:
Introducing FOREIGN KEY constraint 'FK_Comments_Authors_AuthorId' on
table 'Comments' may cause cycles or multiple cascade paths. Specify
ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN
KEY constraints. Could not create constraint or index. See previous
errors
Are there any problems in other relationships? we can discuss

How to create a relation between existing entities in EF core?

I have a case scenario with two tables References and Products alreading containing many entries which can be dynamically related on demand.
public class Reference
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ReferenceId { get; set; }
public string Name { get; set; }
public string Status { get; set; }
public virtual ICollection<Product> ManyProducts { get; set; }
public Reference() {}
}
public class Product
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid ProductId { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
[ForeignKey("Reference")]
public Guid ReferenceId { get; set; }
public virtual Reference OneReference { get; set; }
public Product() {}
}
When a user ask to link a reference to a product I simply do :
product.ReferenceId = reference.ReferenceId ;
await context.SaveChangesAsync() ;
The entry in Products table is updated correctly, but when I try to access a reference's related data, it does not retrieve any ?? After eager loading :
var reference = await context.References
.Include(r => r.ManyProducts)
.SingleAsync(r => r.ReferenceId == referenceId) ;
or explicit loading :
var reference = await context.References.FindAsync(referenceId) ;
await context.Entry(reference).Collection(s => s.ManyProducts).LoadAsync() ;
reference.ManyProducts is empty. So I have to do something like this :
var reference = await context.References.FindAsync(referenceId) ;
var products = await context.Products.Where(l => l.ReferenceId == referenceId).ToListAsync() ;
result.ManyProducts = products ;
which works fine, but I would like to understand why ?
I´m using DataAnnotation
Sample
public class spread
{
[Key]
public int spreadid { get; set; }
[Required]
public DateTime insertdate { get; set; }
[Required]
public int exchangeid { get; set; }
[ForeignKey("exchangeid"), Display(Name = "Exchange origem")]
public virtual exchange exchange { get; set; } // One to one
[ForeignKey("spreadid")]
public virtual ICollection<spreadhelper> spreadhelper { get; set; } // One to many
}
public class spreadhelper
{
[Key]
public int spreadhelperid { get; set; }
[Required]
public int spreadid { get; set; }
[Required]
public int exchangeid { get; set; }
[ForeignKey("exchangeid"), Display(Name = "Exchange")] // One to one
public virtual exchange exchange { get; set; }
[Required, Range(0, 200)]
public decimal spreadvalue { get; set; }
}
one to one - sample
public class exchange
{
[Key]
public int exchangeid { get; set; }
[Required]
public DateTime insertdate { get; set; }
[Required, MaxLength(50)]
public string name { get; set; }
[MaxLength(128)]
public string token { get; set; }
}
One to many sample

Entity Framework: Can't save data because of tracking

I have got a complex class. Feedback and Steps. I am using SQL database and .NET Core 2. I can save main properties but can't save the sub class FeedbackSteps properties
public class FeedbackModel
{
[Key]
public int FeedBackID { get; set; }
public DateTime FBDate { get; set; }
public bool? VideoStatus { get; set; }
public string VideoDetail { get; set; }
public string PITFeedBack { get; set; }
public int ActivityID { get; set; }
public virtual ActivityModel Activity { get; set; }
public int ClientID { get; set; }
public virtual ClientModel Client { get; set; }
public int? SupportPlanID { get; set; }
public virtual SupportPlanModel SupportPlan { get; set; }
public int EmployeeID { get; set; }
public virtual Employee Employee { get; set; }
public bool FeedbackStatus { get; set; } = true;
virtual public List<FeedbackStepModel> FeedbackSteps { get; set; }
}
public class FeedbackStepModel
{
[Key]
public int FeedbackStepID { get; set; }
public int FeedbackID { get; set; } = 0;
public int SupportPlanID { get; set; }
public int StepNumber { get; set; }
public string StepDetail { get; set; }
public string AchievementStatus { get; set; }
public string AchievementComment { get; set; }
}
This is the post method. View returns Edited or Updated feedback and i just want to update the database with new data
[HttpPost]
public IActionResult Edit(FeedbackModel feedback)
{
if (ModelState.IsValid)
{
feedbackRepository.Save(feedback);
TempData["message"] = $"Feedback has been saved";
return RedirectToAction("Index");
}
}
After EDIT, I would like to save it...
public void Save(FeedbackModel feedback)
{
if (feedback.FeedBackID == 0)
{
context.FeedbackModels.Add(feedback);
}
else
{
FeedbackModel dbEntry = context.FeedbackModels.Include(s => s.FeedbackSteps).FirstOrDefault(a => a.FeedBackID == feedback.FeedBackID);
if (dbEntry != null)
{
dbEntry.FeedBackID = feedback.FeedBackID;
dbEntry.FBDate = feedback.FBDate;
dbEntry.VideoStatus = feedback.VideoStatus;
dbEntry.VideoDetail = feedback.VideoDetail;
dbEntry.SupportPlanID = feedback.SupportPlanID;
dbEntry.ActivityID = feedback.ActivityID;
dbEntry.PITFeedBack = feedback.PITFeedBack;
dbEntry.ClientID = feedback.ClientID;
dbEntry.EmployeeID = feedback.EmployeeID;
dbEntry.FeedbackStatus = feedback.FeedbackStatus;
dbEntry.FeedbackSteps = feedback.FeedbackSteps;
}
}
context.SaveChanges();
}
But I get this error all the time
The instance of entity type 'FeedbackStepModel' cannot be tracked because another instance with the key value '{FeedbackStepID: 1}' is already being tracked.
When attaching existing entities, ensure that only one entity instance with a given key value is attached.
Your FeedbackModel update operation with children (FeedbackSteps) should be as follows:
FeedbackModel dbEntry = context.FeedbackModels.Include(s => s.FeedbackSteps).FirstOrDefault(a => a.FeedBackID == feedback.FeedBackID);
if (dbEntry != null)
{
dbEntry.FeedBackID = feedback.FeedBackID;
dbEntry.FBDate = feedback.FBDate;
dbEntry.VideoStatus = feedback.VideoStatus;
dbEntry.VideoDetail = feedback.VideoDetail;
dbEntry.SupportPlanID = feedback.SupportPlanID;
dbEntry.ActivityID = feedback.ActivityID;
dbEntry.PITFeedBack = feedback.PITFeedBack;
dbEntry.ClientID = feedback.ClientID;
dbEntry.EmployeeID = feedback.EmployeeID;
dbEntry.FeedbackStatus = feedback.FeedbackStatus;
dbEntry.FeedbackSteps.Clear(); // First you have to clear the existing feedBackSteps
foreach(FeedbackStep feedBackStep in feedback.FeedbackSteps)
{
dbEntry.FeedbackSteps.Add(feedBackStep); // You have to add new and updated feedBackStep here.
}
}
If dbEntry.FeedbackSteps.Clear(); does not work (may be in EF Core 2.0 or lower Clear() does not work) then replace dbEntry.FeedbackSteps.Clear(); with the following code:
foreach(FeedbackStep feedbackStepToBeRemoved in dbEntry.FeedbackSteps)
{
context.Remove(feedbackStepToBeRemoved);
}

.NET Foreign Key Cannot be Inserted

I have used foreign keys many times before and set up these models just the same however I'm getting this error, the error also occurs when writing usertableID:
A foreign key value cannot be inserted because a corresponding primary key value does not exist. [ Foreign key constraint name = FK_dbo.Outreaches_dbo.OutreachNames_OutreachNamesID ]
Can anyone explain?
Code causing error:
foreach (var item in records)
{
List<string> foundEmails = EmailScraper.Main(item.domain);
string[] emails = foundEmails.ToArray();
var outreach = new Outreach {
domain = item.domain,
email1 = foundEmails.ElementAtOrDefault(0),
email2 = foundEmails.ElementAtOrDefault(1),
email3 = foundEmails.ElementAtOrDefault(2),
email4 = foundEmails.ElementAtOrDefault(3),
email5 = foundEmails.ElementAtOrDefault(4),
email6 = foundEmails.ElementAtOrDefault(5),
UserTableID = UserTableID,
OutreachNamesID = listNumber
};
db.OutreachLists.Add(outreach);
db.SaveChanges();
}
var outreachlist = new OutreachNames
{
ID = listNumber,
listName = model.listName,
listCount = count,
listSent = 0,
unread = 0,
replyRate = 0,
UserTableID = UserTableID,
};
db.OutreachNames.Add(outreachlist);
db.SaveChanges();
Model Outreach:
namespace Linkofy.Models
{
public class Outreach
{
public int ID { get; set; }
public int? OutreachNamesID { get; set; }
public virtual OutreachNames OutreachNames { get; set; }
public string name { get; set; }
[Required]
public string domain { get; set; }
public string email1 { get; set; }
public string email2 { get; set; }
public string email3 { get; set; }
public string email4 { get; set; }
public string email5 { get; set; }
public string email6 { get; set; }
public string email7 { get; set; }
public string email8 { get; set; }
public int? UserTableID { get; set; }
public virtual UserTable UserTable { get; set; }
}
}
Model OutreachNames:
namespace Linkofy.Models
{
public class OutreachNames
{
public int ID { get; set; }
[Required]
public string listName { get; set; }
public int listCount { get; set; }
public int listSent { get; set; }
public int unread { get; set; }
public int replyRate { get; set; }
public virtual ICollection<Outreach> OutreachLists { get; set; }
public int? UserTableID { get; set; }
public virtual UserTable UserTable { get; set; }
}
}
When saving your Outreach you are setting the FK OutreachNamesID to an ID of a record which doesn't exist yet. You need to create this record first or use Entity Framework to create OutreachNames as a child entity. Both entities need to be persisted to the db in one transaction.
You can create the child entity inside of the parent and persist them in one go like this:
var outreach = new Outreach
{
OutreachNames = new OutreachNames
{
...
}
}
db.OutreachLists.Add(outreach);
db.SaveChanges();

Entity Framework Null Foreign Keys on Seed

I'm trying to figure out what is going on here. When I seed my database, my foreign key that it generates is always null. My model is simple:
public class PnlTarget
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PnlTargetId { get; set; }
public ReferenceAsset Underlyer { get; set; }
public decimal Target { get; set; }
public virtual PnlSettings PnlSettings { get; set; }
}
public class PnlSettings
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int PnlSettingsId { get; set; }
public ColloquialType Type { get; set; }
public virtual PnlTarget SPTSX60 { get; set; }
public virtual PnlTarget SPTXLVPR { get; set; }
public virtual PnlTarget STBANKX { get; set; }
public virtual PnlTarget SX5E { get; set; }
public virtual PnlTarget RTY { get; set; }
public virtual PnlTarget SPX { get; set; }
[DataType(DataType.DateTime)]
public DateTime LastEdited { get; set; }
public string LastEditedBy { get; set; }
}
So it's a 1..0 to many relationship. When I seed it with something like this:
PnlSettings vanillaAccelerator = new PnlSettings
{
PnlSettingsId = 1,
Type = ColloquialType.VanillaAccelerator,
RTY = new PnlTarget {Underlyer = ReferenceAsset.RTY, Target = (decimal) 0.004},
SPX = new PnlTarget {Underlyer = ReferenceAsset.SPX, Target = (decimal) 0.004},
SPTSX60 = new PnlTarget { Underlyer = ReferenceAsset.SPTSX60, Target = (decimal)0.004},
SPTXLVPR = new PnlTarget { Underlyer = ReferenceAsset.SPTXLVPR, Target = (decimal)0.004},
STBANKX = new PnlTarget { Underlyer = ReferenceAsset.STBANKX, Target = (decimal)0.004},
SX5E = new PnlTarget { Underlyer = ReferenceAsset.SX5E, Target = (decimal)0.004},
LastEdited = DateTime.Now,
LastEditedBy = "SEED"
};
My foreign key property is always null as illustrated here. I've tried implementing a foreign key property manually using the [ForeignKey] annotation but unfortunately it still generates this null column. Is this intended?
Thanks!

Categories