How to insert values into virtual fields - c#

I have a learner table that i set values to on a user registration, 'Register(RegisterViewModel model)' in the AccountController.
if (result.Succeeded)
{
await SignInManager.SignInAsync(user, isPersistent:false, rememberBrowser:false);
using (The_FactoryDBContext db = new The_FactoryDBContext())
{
Learner learner = new Learner();
learner.learnerID = User.Identity.GetUserId();
learner.llCounter = 0;
learner.dtwCounter = 0;
learner.ftwCounter = 0;
learner.counter = 0;
db.Learners.Add(learner);
db.SaveChanges();
}
}
}
This is how my learner auto generated class looks with some virtual fields.
public partial class Learner
{
public Learner()
{
this.Learner_Treasure = new HashSet<Learner_Treasure>();
}
public string learnerID { get; set; }
public int llCounter { get; set; }
public int dtwCounter { get; set; }
public int ftwCounter { get; set; }
public int counter { get; set; }
public virtual AspNetUser AspNetUser { get; set; }
public virtual ICollection<Learner_Treasure> Learner_Treasure { get; set; }
}
}
However i get this error upon registration and i dont know how to fix it, can someone help me, or is my code perhaps in the wrong place?
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Learner_AspNetUsers1". The conflict occurred in database "The_Factory", table "dbo.AspNetUsers", column 'Id'.
AspNetUser class
public partial class AspNetUser
{
public AspNetUser()
{
this.AspNetUserClaims = new HashSet<AspNetUserClaim>();
this.AspNetUserLogins = new HashSet<AspNetUserLogin>();
this.AspNetRoles = new HashSet<AspNetRole>();
}
public string Id { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public Nullable<System.DateTime> LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public int AvatarID { get; set; }
public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
public virtual Avatar Avatar { get; set; }
public virtual Learner Learner { get; set; }
public virtual ICollection<AspNetRole> AspNetRoles { get; set; }
}
}

Try with
[ForeignKey("AspNetUser")]
over learnerID property. The reason is that EF has no clue that you are creating a 1-1 mapping from learner to user (and that the PK in learner is also the FK to user). Putting this attribute will tell EF about your design.

Related

How to delete all related entities from database with Entity Framework code-first

I have a problem with related entities deletion. For example, I need to delete one of series from user series collection. When this happens I want all of related to this series records in database to be deleted. How to do it? Please provide example, I'm stuck a little. Thank you!
public class User
{
public Guid UserId { get; set; }
public virtual List<Series> UserSeries { get; set; }
}
public class DropPhoto
{
public Guid DropPhotoId { get; set; }
public virtual SimpleLine SimpleHorizontalLine { get; set; }
public virtual SimpleLine SimpleVerticalLine { get; set; }
public virtual Drop Drop { get; set; }
}
public class ReferencePhoto
{
public Guid ReferencePhotoId { get; set; }
public virtual SimpleLine SimpleLine { get; set; }
}
public class Series
{
public Guid SeriesId { get; set; }
public virtual List<DropPhoto> DropPhotosSeries { get; set; }
public virtual ReferencePhoto ReferencePhotoForSeries { get; set; }
}
public class SimpleLine
{
public Guid SimpleLineId { get; set; }
}
public class Drop
{
public Guid DropId { get; set; }
}
You are actually looking for cascade delete.
For details please look at https://www.entityframeworktutorial.net/code-first/cascade-delete-in-code-first.aspx
Here is an example
public class Student
{
public int StudentId { get; set; }
public string StudentName { get; set; }
public virtual StudentAddress Address { get; set; }
}
public class StudentAddress
{
[ForeignKey("Student")]
public int StudentAddressId { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public int Zipcode { get; set; }
public string State { get; set; }
public string Country { get; set; }
public virtual Student Student { get; set; }
}
The following example demonstrates the cascade delete operation
using (var ctx = new SchoolContext())
{
var stud = new Student() { StudentName = "James" };
var add = new StudentAddress() { Address1 = "address" };
stud.Address = add;
ctx.Students.Add(stud);
ctx.SaveChanges();
ctx.Students.Remove(stud);// student and its address will be removed from db
ctx.SaveChanges();
}

DbUpdateException when adding item to Entity Framework Context

I have the following two classes:
public class Record
{
public int RecordId { get; set; }
public DateTime? InsertDate { get; set; } = DateTime.Now;
public DateTime BookingDate { get; set; }
public string AmountTypeName { get; set; }
public double? Amount { get; set; }
public string BookingAccountID { get; set; }
public string AccountCurrency { get; set; }
public string ClientCurrency { get; set; }
public string AffectsBalance { get; set; }
public double? AmountAccountCurrency { get; set; }
public string AmountClientCurrency { get; set; }
public int UnifiedInstrumentCode { get; set; }
public InstrumentInfo InstrumentInfo { get; set; }
}
public class InstrumentInfo
{
[Key]
public int UnifiedInstrumentCode { get; set; }
public ICollection<Record> Record { get; set; }
public string AssetType { get; set; }
public int UnderlyingInstrumentUic { get; set; }
public string UnderlyingInstrumentSubType { get; set; }
public string InstrumentSymbol { get; set; }
public string InstrumentDescription { get; set; }
public string InstrumentSubType { get; set; }
public string UnderlyingInstrumentAssetType { get; set; }
public string UnderlyingInstrumentDescription { get; set; }
public string UnderlyingInstrumentSymbol { get; set; }
}
that I want to use as my context for EF6.
I defined the context the following way:
public class TransactionsContext: DbContext
{
public DbSet<Record> Records { get; set; }
public DbSet<InstrumentInfo> InstrumentInfos { get; set; }
public TransactionsContext()
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<TransactionsContext>(null);
base.OnModelCreating(modelBuilder);
}
}
If I run a test against it that shall add and InstrumentInfo object to the DB
[TestMethod]
public void AddInstrumentInfo_Added_IsTrue()
{
InstrumentInfo info = FakeFactory.GetInstrumentInfo();
using (var ctx = new TransactionsContext())
{
ctx.InstrumentInfos.Add(info);
ctx.SaveChanges();
}
}
I get the following exception:
SqlException: Cannot insert the value NULL into column
'UnifiedInstrumentCode', table
'TransactionsContext.dbo.InstrumentInfoes'; column does not allow
nulls. INSERT fails. The statement has been terminated.
I tried all different scenarios that I found here but I couldn't figure out what I'm doing wrong.
The ultimate goal is that i define my two classes in a way so that a "Record" is linked to the "InstrumentInfo" table via the "UnifiedInstrumentCode" property.
My guess is that my constraints for this two tables are still not correct, but I cant figure out how to define it in EF6 (code first) to get this working.
Adding the annotation [DatabaseGenerated(DatabaseGeneratedOption.None)] to my primary key in InstrumentInfo solved the problem:
public class InstrumentInfo
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int UnifiedInstrumentCode { get; set; }
public ICollection<Record> Record { get; set; }
public string AssetType { get; set; }
public int UnderlyingInstrumentUic { get; set; }
public string UnderlyingInstrumentSubType { get; set; }
public string InstrumentSymbol { get; set; }
public string InstrumentDescription { get; set; }
public string InstrumentSubType { get; set; }
public string UnderlyingInstrumentAssetType { get; set; }
public string UnderlyingInstrumentDescription { get; set; }
public string UnderlyingInstrumentSymbol { get; set; }
}
I did not investigate further but my guess is that if a new Record is added, EF initially creates and InstrumentInfo object that has a Null Value for its Primary key which causes the Exception.
I hope it helps if somebody runs into the same problem in future.

SQL Exception trying to add an existing user when context.SaveChanges() on a different table

I am trying to add an entry to a table that holds a users browsing history information. However, when trying to save the addition an SqlException is thrown:
Cannot insert duplicate key row in object 'dbo.AspNetUsers' with
unique index 'UserNameIndex'. The duplicate key value is
(exampleUserName). The statement has been terminated.
A user is has many browsing histories but a browsing history can only be attached to one user so there is a user as part of the BrowsingHistory DataModel:
namespace DataModels
{
[Table("BrowsingHistory")]
public class BrowsingHistory
{
[Key]
public int BrowsingHistoryId { get; set; }
public int ProductId { get; set; }
public System.DateTime DateTime { get; set; }
public int DeviceId { get; set; }
public int UserId { get; set; }
public virtual AspNetUsers User { get; set; }
public virtual Device Device { get; set; }
public virtual Product Product { get; set; }
}
}
It is to note that I am using the Microsoft Identity classes for my authentication. The user class looks as follows:
namespace DataModels
{
using System;
using System.Collections.Generic;
[Table("AspNetUsers")]
public class AspNetUsers
{
public AspNetUsers()
{
BrowsingHistories = new HashSet<BrowsingHistory>();
Orders = new HashSet<Order>();
AspNetUserClaims = new HashSet<AspNetUserClaims>();
AspNetRoles = new HashSet<AspNetRoles>();
}
[Key]
public int Id { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public DateTime? LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public string HouseName { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string AddressLine3 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
public string ContactNumber { get; set; }
public virtual ICollection<BrowsingHistory> BrowsingHistories { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public virtual ShoppingCart ShoppingCart { get; set; }
public virtual ICollection<AspNetUserClaims> AspNetUserClaims { get; set; }
public virtual ICollection<AspNetRoles> AspNetRoles { get; set; }
}
}
The error occurs when trying to save the addition in the repository. On the _context.SaveChanges() line the method below.
public void CreateBrowsingHistoryEntry(BrowsingHistory bhe)
{
_context.BrowsingHistory.Add(bhe);
_context.SaveChanges();
}
Any help with this issue would be greatly appreciated.

Entity Framework How to generate PrimaryKey by mask

I need to generate a primary key by mask (for example: BS{100-999}-{Rand(100-999)}) But I do not know how to generate a key like this in EF code/ Could somebody help me please to figure this out?
My model:
[Table("Tickets")]
public class Ticket
{
public Ticket()
{
CreationDate = DateTime.UtcNow;
LastChangeDate = DateTime.UtcNow;
UserReviewed = true;
EmailAlert = true;
}
[Key]
[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; } //now it is Guid But i need this to be string and generated by the above mask
public string UsersName { get; set; }
public string Theme { get; set; }
public string Request { get; set; }
public DateTime CreationDate { get; set; }
public string TypeMask { get; set; }
public string StatusMask { get; set; }
public int SenderId { get; set; }
public bool EmailAlert { get; set; }
public DateTime LastChangeDate { get; set; }
public bool UserReviewed { get; set; }
public virtual ICollection<TicketRecord> Answers { get; set; }
[ForeignKey("StatusMask")]
public virtual TicketStatus Status { get; set; }
[ForeignKey("TypeMask")]
public virtual TicketType Type { get; set; }
[ForeignKey("SenderId")]
public virtual UserProfile Sender { get; set; }
public virtual AttachmentsCollection IncludedFiles { get; set; }
}
EF never generates keys. Either you need to generate the key by yourself or you let the EF know that the key will be generated by the database using StoreGeneragedPattern annotation/setting. EF cannot generate keys as it cannot guarantee uniquenesses for the generated values.

How to join Aspnet_User to my custom user

I have a User model object and I wan't to when I get this object to get aspnet_User object with it for additional data (usename etc.)
public class User
{
public Guid UserId_fk { get; set; }
public int UserId { get; set; }
public string FirstName { get; set; }
public virtual AspnetUsers AspnetUsers { get; set; }
}
public class AspnetUsers
{
public Guid ApplicationId { get; set; }
public Guid UserId { get; set; }
public string UserName { get; set; }
public string LoweredUserName { get; set; }
public string MobileAlias { get; set; }
public bool IsAnonymous { get; set; }
public DateTime LastActivityDate { get; set; }
}
In database UserId_fk is FK to aspnet_Users.UserId.
How to map this?

Categories