I am working on Entity Framework 6 and repositories setup to do crud operations. I am trying to insert record in one of the table and getting error for null entries even duo it is not.
{"Cannot insert the value NULL into column 'UI_ID', table 'Blackpool_BPM.dbo.COURSE_INSTANCE'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated."}
The connection to database is correct as I can read data with no problem
At Generic Repository, getting data correctly, just before Save()
Table Structure
Class Model
[Table("COURSE_INSTANCE")]
public class BIZCourseInstanceEntity
{
[Key]
public int UI_ID { get; set; }
public string UnitInstanceCode { get; set; }
public string FESLongDescription { get; set; }
public string FESShortDescription { get; set; }
public string FullDescription { get; set; }
public string OwningOrganisationCode { get; set; }
public int? OwningOrganisationID { get; set; }
public string TopicCode { get; set; }
public string UnitCategory { get; set; }
public string UnitCode { get; set; }
public string FESQualificationType { get; set; }
public int? SCHOOLS { get; set; }
public int? MARKETING_GROUPS { get; set; }
}
Repository
public class BIZCourseInstanceRepository : GenericRepository<BIZCourseInstanceEntity>
{
public BIZCourseInstanceRepository() { }
public BIZCourseInstanceRepository(DbContext dbContext)
:base(dbContext)
{ }
}
Unit of work class
public class BIZ_UOF : IDisposable
{
private BIZDbContext _BIZDbContextObject = new BIZDbContext();
protected BIZCourseInstanceRepository _BIZCourseInstanceRepository;
public BIZCourseInstanceRepository BIZCourseInstanceRepository
{
get
{
if (this._BIZCourseInstanceRepository == null)
{
this._BIZCourseInstanceRepository = new BIZCourseInstanceRepository(_BIZDbContextObject);
}
return _BIZCourseInstanceRepository;
}
}
/////
public void Save()
{
_BIZDbContextObject.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
_BIZDbContextObject.SaveChanges();
}
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_BIZDbContextObject.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
DbContext
public class BIZDbContext : BaseContext<BIZDbContext>
{
public BIZDbContext() : base("_DbContext")
{ }
public DbSet<BIZCourseInstanceEntity> BIZ_CourseInstance { get; set; }
}
Generic Repository CRUD
public void InsertEntity(TEntity obj)
{
_DbSet.Add(obj);
}
Function class where Error is generating at Save()
public void InsertCourseInstance()
{
BIZCourseInstanceEntity BIZCourseInstanceEntityObject = null;
BIZCourseInstanceEntityObject = new BIZCourseInstanceEntity
{
UI_ID = 999999,
UnitInstanceCode = "KZ999999",
FESLongDescription = "LONG",
FESShortDescription = "SHORT",
FullDescription = "FULL",
OwningOrganisationCode = "E",
OwningOrganisationID = 155,
TopicCode = "04.1",
UnitCategory = "04",
UnitCode = "HE-G",
FESQualificationType = null,
SCHOOLS = 5,
MARKETING_GROUPS = 44
};
using (var _uow = new BIZ_UOF())
{
_uow.BIZCourseInstanceRepository.InsertEntity(BIZCourseInstanceEntityObject);
_uow.Save();
}
}
You need to tell Entity Framework that your ID is an identity field. If it isn't set up as that in the database, then you need to do that. Otherwise, you'll need to query for the next available ID, and then hope you don't collide with another request trying to save something at the same time.
[Table("COURSE_INSTANCE")]
public class BIZCourseInstanceEntity
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int UI_ID { get; set; }
...
}
If you absolutely have to work without any sort of database generated options for your Primary Key, you can instead use the DatabaseGeneratedOption.None value of the enum. This should be avoided to prevent collisions on your PK, but the option does exist.
I have found answer, the problem was in my database I am require to provide the Primary key which in my case is UI_ID but in my model I haven't define DatabaseGeneredOption.None, hence throwing error, Thanks for Krillgar guiding me
here is updated model
[Table("COURSE_INSTANCE")]
public class BIZCourseInstanceEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int UI_ID { get; set; }
[StringLength(255)]
public string UnitInstanceCode { get; set; }
[StringLength(255)]
public string FESLongDescription { get; set; }
[StringLength(255)]
public string FESShortDescription { get; set; }
[StringLength(255)]
public string FullDescription { get; set; }
[StringLength(255)]
public string OwningOrganisationCode { get; set; }
public int? OwningOrganisationID { get; set; }
[StringLength(255)]
public string TopicCode { get; set; }
[StringLength(255)]
public string UnitCategory { get; set; }
[StringLength(255)]
public string UnitCode { get; set; }
[StringLength(50)]
public string FESQualificationType { get; set; }
public int? SCHOOLS { get; set; }
public int? MARKETING_GROUPS { get; set; }
}
Related
I'm working in asp.net.core Entityframework 6, CodeFirst Approach. I believe i'm seeding the data in a wrong order, or in the wrong way.
I use a similar approach for artist/author/voice/associatedNames. i get similar error as all of them.
The entire error reads for artist or author
SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_AssociatedNames_artistModels_ArtistModelArtistId". The conflict occurred in database "BookDB", table "dbo.artistModels", column 'ArtistId'.
What is the correct way of saving the moduls?
I read this articale EF Code First The INSERT statement conflicted with the FOREIGN KEY constraint This is where i believe i'm approaching the saving wrong.
Edit: i managed to recreated the problem, in another project and got the same error.
public class BookModel
{
[Key]
public int BookId { get; set; }
public ICollection<AssociatedNames>? AssociatedNames { get; set; }
public ICollection<AuthorModel>? Authormodels { get; set; }
}
public class AssociatedNames
{
[Key]
public int AssociatedNamesId { get; set; }
public string? nameString { get; set; }
public int? BookId{ get; set; }
public BookModel? bookModel { get; set; }
public int? AuthorId { get; set; }
public AuthorModel AuthorModel { get; set; }
}
public class AuthorModel
{
[Key]
public int AuthorID { get; set; }
public string Firstname { get; set; }
public ICollection<AssociatedNames>? AssociatedNames { get; set; }
public int? BookId { get; set; }
public BookModel? bookModel{ get; set; }
}
public class SeedData
{
private readonly UserManager<IdentityUser> userManager;
private readonly SignInManager<IdentityUser> signInManager;
private readonly BookDBContext bookDBContext;
public AuthorModel AuthorModels { get; set; }
public BookModel BookModels { get; set; }
public AssociatedNames _AssociatedNames { get; set; }
public SeedData(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager, BookDBContext bookDBContext)
{
this.userManager = userManager;
this.signInManager = signInManager;
this.bookDBContext = bookDBContext;
}
public async Task seedData()
{
var user = new IdentityUser
{
UserName = "TestUSer",
Email = "TestUser#hotmail.com",
};
var newAuthor = new AuthorModel { FirstName = "Charles" };
bookDBContext.AuthorModels.Add(newAuthor);
var newAss = new AssociatedNames { nameString = "Kallax" };
bookDBContext.AssociatedNames.Add(newAss);
var Newbook = new BookModel { BookName = "HelloWorld", AssociatedNames = new List<AssociatedNames> { newAss } };
bookDBContext.SaveChanges();
var result = await userManager.CreateAsync(user, "Test!112");
}
}
On the Program.cs
builder.Services.AddScoped<SeedData>();
static void SeedDatainitialize(IHost host)
{
var scopefactorty = host.Services.GetService<IServiceScopeFactory>();
using (var scope = scopefactorty.CreateScope())
{
var seed = scope.ServiceProvider.GetService<SeedData>();
seed.seedData().Wait();
}
}
The Context.
public class BookDBContext : IdentityDbContext
{
public BookDBContext(DbContextOptions<BookDBContext> options) : base(options)
{
}
public DbSet<AuthorModel> AuthorModels { get; set; }
public DbSet<AssociatedNames> AssociatedNames { get; set; }
public DbSet<BookModel> BookModels { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
I tried using different void methods to save them at different time, so they are fully created at different stages. Then add the object to the collections. and repeat. Did not work
So i solved it, i am unsure why this worked. Either EF had problems with keying the right FK.
public class AssociatedNames
{
[Key]
public int AssociatedNamesId { get; set; }
public string? nameString { get; set; }
public int? BookModelId{ get; set; }
public BookModel? BookModels{ get; set; }
[ForeignKey("AuthorModel")]
public int? AuthorID { get; set; }
public AuthorModel AuthorModel { get; set; }
[ForeignKey("ArtistModel")]
public int? ArtistId { get; set; }
public ArtistModel ArtistModel { get; set; }
[ForeignKey("VoiceActorModel")]
public int? VoiceActorId { get; set; }
public VoiceActorModel VoiceActorModel { get; set; }
}
In my Model Creation i added these lines.
modelBuilder.Entity<BookModel>().Navigation(e => e.Authormodels).AutoInclude();
modelBuilder.Entity<BookModel>().Navigation(e => e.ArtistModels).AutoInclude();
modelBuilder.Entity<BookModel>().Navigation(e => e.VoiceActors).AutoInclude();
I noticed when i wrote the code that i didn't include the other classes when calling, then adding the AssociatedNames.
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.
I'm bulding an application and when I want to insert a form into my form table I get the following error:
Cannot insert explicit value for identity column in table 'Relation'
when IDENTITY_INSERT is set to OFF.
These are my models:
Form model:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("FormType")]
public int? TypeId { get; set; }
public virtual FormType Type { get; set; }
[ForeignKey("FormStatusType")]
public int? StatusTypeId { get; set; }
public virtual FormStatusType StatusTknype { get; set; }
[ForeignKey("Relation")]
public int? SupplierId { get; set; }
public virtual Relation Supplier { get; set; }
[ForeignKey("Relation")]
public int? CustomerId { get; set; }
public virtual Relation Customer { get; set; }
public String SupplierReference { get; set; }
public Guid ApiId { get; set; }
public DateTime DueDate { get; set; }
public FormFile FormFiles { get; set; }
public String FormName { get; set; }
public DateTime UploadDate { get; set; }
Relation model:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[ForeignKey("FormType")]
public int? TypeId { get; set; }
public virtual FormType Type { get; set; }
[ForeignKey("FormStatusType")]
public int? StatusTypeId { get; set; }
public virtual FormStatusType StatusTknype { get; set; }
[ForeignKey("Relation")]
public int? SupplierId { get; set; }
public virtual Relation Supplier { get; set; }
[ForeignKey("Relation")]
public int? CustomerId { get; set; }
public virtual Relation Customer { get; set; }
public String SupplierReference { get; set; }
public Guid ApiId { get; set; }
public DateTime DueDate { get; set; }
public FormFile FormFiles { get; set; }
public String FormName { get; set; }
public DateTime UploadDate { get; set; }
My context looks like this:
public class DataContext: DbContext
{
public DataContext(DbContextOptions<DataContext> options): base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
base.OnConfiguring(optionsBuilder);
optionsBuilder.UseSqlServer();
}
public DbSet<Relation> Relation { get; set; }
public DbSet<Setting> Settings { get; set; }
public DbSet<Notification> Notification { get; set; }
public DbSet<FormStatusType> FormStatusType { get; set; }
public DbSet<File> File { get; set; }
public DbSet<FormFile> FormFile { get; set; }
public DbSet<FormType> FormType { get; set; }
public DbSet<Form> Form { get; set; }
public DbSet<User> User { get; set; }
public DbSet<RelationUser> RelationUser { get; set; }
public DbSet<SupplierCustomer> SupplierCustomer { get; set; }
}
The method I use to add a form looks like this:
public async Task<Form> AddForm(Form form, int currentUserId)
{
try
{
if (form != null)
{
//huidige gebruiker als supplier aanduiden
Relation r = await GetCurrentUser(currentUserId);
form.Supplier = r;
form.SupplierId = r.Id;
//form aan de db toevoegen
_datacontext.Form.Add(form);
_datacontext.SaveChanges();
return form;
}
else
{
return null;
}
}
catch (Exception e)
{
LogError(e);
return null;
}
}
The get current user method
private async Task<Relation> GetCurrentUser(int currentUserId)
{
var relation = from r in _datacontext.RelationUser
where r.UserId == currentUserId
select r.Relation;
return await relation.FirstOrDefaultAsync();
}
This is where I call the AddForm method:
[HttpPost]
[Route("addform")]
[Authorize]
// api/form/addform
public async Task<IActionResult> AddForm([FromBody] Form form)
{
if (ModelState.IsValid)
{
Form f = await _formRepository.AddForm(form, GetUserIdFromToken());
if(f != null)
{
QueueObject qo = new QueueObject()
{
ActionTypeId = 1,
FormId = f.Id
};
await new QueueHandler().SendMessageToQueue(qo);
}
return Ok(f);
}
else
{
return NotFound("model is niet geldig");
}
}
I already searched but found nothing that solved the problem
Another possible reason this may happen, is if you have a timeout in some call to SaveChanges when trying to insert new entities to your database, then try calling SaveChanges again, using the same DbContext instance.
This is reproducible:
using(var context = new MyDbContext())
{
context.People.Add(new Person("John"));
try
{
// using SSMS, manually start a transaction in your db to force a timeout
context.SaveChanges();
}
catch(Exception)
{
// catch the time out exception
}
// stop the transaction in SSMS
context.People.Add(new Person("Mike"));
context.SaveChanges(); // this would cause the exception
}
This last SaveChanges would cause Cannot insert explicit value for identity column in table 'People' when IDENTITY_INSERT is set to OFF.
You have multiple errors on your model. The ForeignKey attribute must point to properties in the class, not to the type of the dependent entity:
//FORM MODEL
[ForeignKey("Type")]
public int? TypeId { get; set; }
public virtual FormType Type { get; set; }
[ForeignKey("StatusTknype")]
public int? StatusTypeId { get; set; }
public virtual FormStatusType StatusTknype { get; set; }
[ForeignKey("Supplier")]
public int? SupplierId { get; set; }
public virtual Relation Supplier { get; set; }
[ForeignKey("Customer")]
public int? CustomerId { get; set; }
public virtual Relation Customer { get; set; }
//RELATION MODEL
[ForeignKey("Type")]
public int? TypeId { get; set; }
public virtual FormType Type { get; set; }
[ForeignKey("StatusTknype")]
public int? StatusTypeId { get; set; }
public virtual FormStatusType StatusTknype { get; set; }
[ForeignKey("Relation")]
public int? SupplierId { get; set; }
public virtual Relation Supplier { get; set; }
[ForeignKey("Customer")]
public int? CustomerId { get; set; }
public virtual Relation Customer { get; set; }
Also, if you followed Convention Over Configuration, you could drop the ForeignKeyAttribute completely by just naming the properties conventionally:
public int? StatusTypeId { get; set; }
public virtual FormStatusType StatusType { get; set; }
Pretty new to ASP.NET and programming. I have two models, two API controllers, two repositories. How do I post the data to the second model while attaching it to the first (I'm guessing by ID.) Do I possibly need a View Model? Also reading a little about unit of work. Maybe neither are necessary? Below is some code. Thanks!
Record.cs
namespace Train.Models {
public class Record {
public int Id { get; set; }
public int Quantity { get; set; }
public DateTime DateCreated { get; set; }
public bool IsActive { get; set; }
public string UserId { get; set; }
public virtual ICollection<Cars> Cars { get; set; }
}
}
Cars.cs
namespace Train.Models {
public class Cars {
public int Id { get; set; }
public string EmptyOrLoaded { get; set; }
public string CarType { get; set; }
//Hopper, flatbed, tank, gondola, etc.
public string ShippedBy { get; set; }
//UP(Union Pacific) or BNSF
public string RailcarNumber { get; set; }
//public virtual ApplicationUser ApplicationUser { get; set; }
public string UserId { get; set; }
public string RecordId { get; set; }
public virtual Record Record { get; set; }
}
}
Record Repository
public void SaveRecord(Record recordToSave) {
if (recordToSave.Id == 0) {
recordToSave.DateCreated = DateTime.Now;
_db.Record.Add(recordToSave);
_db.SaveChanges();
} else {
var original = this._db.Record.Find(recordToSave.Id);
original.Quantity = recordToSave.Quantity;
original.IsActive = true;
_db.SaveChanges();
}
}
EFRepository (Cars)
public void SaveCar(Cars carToSave) {
if (carToSave.Id == 0) {
_db.Cars.Add(carToSave);
_db.SaveChanges();
} else {
var original = this.Find(carToSave.Id);
original.EmptyOrLoaded = carToSave.EmptyOrLoaded;
original.CarType = carToSave.CarType;
original.ShippedBy = carToSave.ShippedBy;
original.RailcarNumber = carToSave.RailcarNumber;
_db.SaveChanges();
}
}
I have a view in my SQL database. All I want is to retrieve data from that view.
I have added POCO class.
namespace WFPersistence.DataModel
{
public class Instance
{
public Guid InstanceId { get; set; }
public DateTime? PendingTimer { get; set; }
public DateTime? CreationTime { get; set; }
public DateTime? LastUpdatedTime { get; set; }
public int? ServiceDeploymentId { get; set; }
public string SuspensionExceptionName { get; set; }
public string SuspensionReason { get; set; }
public string ActiveBookmarks { get; set; }
public string CurrentMachine { get; set; }
public string LastMachine { get; set; }
public string ExecutionStatus { get; set; }
public bool? IsInitialized { get; set; }
public bool? IsSuspended { get; set; }
public bool? IsCompleted { get; set; }
public byte? EncodingOption { get; set; }
public byte[] ReadWritePrimitiveDataProperties { get; set; }
public byte[] WriteOnlyPrimitiveDataProperties { get; set; }
public byte[] ReadWriteComplexDataProperties { get; set; }
public byte[] WriteOnlyComplexDataProperties { get; set; }
public string IdentityName { get; set; }
public string IdentityPackage { get; set; }
public long? Build { get; set; }
public long? Major { get; set; }
public long? Minor { get; set; }
public long? Revision { get; set; }
}
public class Instances : Collection<Instance>
{
}
}
This is how I am trying to map with view.
public class WFPersistenceStore : DbContext
{
public WFPersistenceStore() : base("WFPersist")
{
}
public DbSet<Instance> PersistedInstances { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Instance>().ToTable("System.Activities.DurableInstancing.Instances");
}
}
This is how I am connecting with view
using (var PersistStore = new WFPersistenceStore())
{
var result = from t in PersistStore.PersistedInstances
select t;
////
///
}
I am getting this error:
An unhandled exception of type 'System.ArgumentException' occurred in
RentalHost.exe
Additional information: The database name
'System.Activities.DurableInstancing.Instances' is invalid. Database
names must be of the form [.].
Your method should be like
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Instance>().ToTable("Instances");
}
I have resolved my issue by just putting the following line inside the constructor of my context class (i.e. WFPersistenceStore).
Database.SetInitializer<WFPersistenceStore>(null);
This wasn't mentioned anywhere clearly in official documents if i am not wrong.
The above line needed for EF6 version only but not required for earlier versions of EF.