Error while inserting in a table containing identity column System.Data.Entity.Infrastructure.DbUpdateException - asp.net-mvc-4

In my ASP.Net MVC 4 project I'm trying to insert data into a table which has identity an auto-increment column (ACTIVITYID), which is the Primary Key.
Table Class
public partial class ACTIVITY
{
public decimal ACTIVITYID { get; set; }
public Nullable<decimal> CALLTICKETNUMBER { get; set; }
public string ACTION { get; set; }
public Nullable<long> STATUSIDATTHETIMEOFACTION { get; set; }
public short RECORDFORDISPLAY { get; set; }
public Nullable<System.DateTime> ACTIVITYDATE { get; set; }
public string USER_ { get; set; }
public virtual CALLTICKET CALLTICKET { get; set; }
}
Upon calling the following method generates exception
public static void AddActivity(long ticketNumber, string action, string userId, int? previousStatusId = null)
{
var newActivity = new ACTIVITY
{
ACTION = action,
ACTIVITYDATE = System.DateTime.Now,
CALLTICKETNUMBER = ticketNumber,
STATUSIDATTHETIMEOFACTION = previousStatusId,
USER_ = userId,
};
dbOraContext.ACTIVITies.Add(newActivity);
dbOraContext.SaveChanges();
}
While viewing ACTIVITies.Add(newActivity) ACTIVITYID is inserting with value 0.
On tracing the inner exception following exception is displayed:
{"ORA-00001: unique constraint (ATM_CRM.PK_ACTIVITY) violated"}
Also, an exception of type 'System.Data.Entity.Infrastructure.DbUpdateException' occurred.
Earlier I have worked with MS SQL Server, and never encountered such a problem. Auto-increment column should automatically get its value.
Note that I'm working on Oracle DB.

Related

Microsoft.EntityFrameworkCore.DbUpdateException

I have a comment table where it have a two foreign key(i.e Userid and postid). I was trying to insert data into comment table using these two foreign key but was unable to insert. This is my post table
public class Post
{
public int Id { get; set; }
public string PostText { get; set; }
public string Title { get; set; }
public bool Status { get; set; }
public DateTime PostDate { get; set; }
public virtual List<Comment> Comments { get; set; }
public ApplicationUser ApplicationUser { get; set; }
}
And this is my comment table
public class Comment
{
public int Id { get; set; }
public string CommentText { get; set; }
public DateTime CommentTime { get; set; }
public bool Status { get; set; }
public ApplicationUser CommentBy { get; set; }
public Post Posts { get; set; }
}
Comment service
public void Save(Comment comment)
{
_context.Set<Comment>().Add(comment);
_context.SaveChanges();
}
And this is my controller
[HttpPost]
public ObjectResult SaveComment([FromBody] Comment comment)
{
if (ModelState.IsValid)
{
try
{
_commentService.Save(comment);
return Ok("comment saved");
} catch (Exception e)
{
return BadRequest(e);
}
} else
{
return BadRequest("Model is not valid");
}
}
And the error is
{Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.SqlClient.SqlException: Violation of PRIMARY KEY constraint 'PK_AspNetUsers'. Cannot insert duplicate key in object 'dbo.AspNetUsers'. The duplicate key value is (966fc417-8757-4bac-89b2-9975d4f2cd41).
Cannot insert explicit value for identity column in table 'Posts' when IDENTITY_INSERT is set to OFF.
The statement has been terminated.
this is my api request
The reason is that you will also insert a new comment.CommentBy when you're inserting a brand new comment:
// the `comment` here is constructed by model binding, which is a brand new entity
[HttpPost]
public ObjectResult SaveComment([FromBody] Comment comment)
{
// ...
_commentService.Save(comment); // save the brand new comment
// ...
}
"A brand new comment" means this Comment entity and its related propreties are all untracked. When saving a brand new entity, EF Core will also create related entities for you automatically.
To avoid this behavior, you could mark the state of comment.CommentBy as Unchanged,
_context.Entry(comment.CommentBy).State= EntityState.Unchanged;
so that the EF Core will not create a new CommentBy (i.e. an ApplicationUser) for you. But be careful: you must make sure the ApplicationUser already exists.
The same goes Post.
Another approach is much safer. As suggested by #Khai Nguyen in the comment, you should get ApplicationUser and Post instance from database, so that the EF Core knows there's already a ApplicationUser and a Post within database and won't insert new ApplicationUser or Post for you.

Error with EF core savecontext using Identity class

I have a quiz sql schema and I am also using ASP.NET Identity. When I attempt to insert an answer from the user into the UserAnswer table I get the error below. It seems like it is trying to insert into the User table but I don't want that?
Violation of PRIMARY KEY constraint 'PK_AspNetUsers'. Cannot insert
duplicate key in object 'dbo.AspNetUsers'. The duplicate key value is
(71ddfebf-18ba-4214-a01e-42ca0f239804). Cannot insert explicit value
for identity column in table 'Questions' when IDENTITY_INSERT is set
to OFF. The statement has been terminated.
foreach (ProfileViewModel pvm in profileViewModels)
{
UserAnswer ua = new UserAnswer();
ua.QuestionId.ID = pvm.Question.ID;
ua.ApplicationUser.Id = userId;
ua.AnswerText = pvm.Answer;
_userAnswerRepository.Create(ua);
}
which just does
protected void Save() => _context.SaveChanges();
and the model is
public class UserAnswer
{
public UserAnswer()
{
this.QuestionId = new Question();
this.ApplicationUser = new ApplicationUser();
}
public int Id { get; set; }
public ApplicationUser ApplicationUser { get; set; }
public Question QuestionId { get; set; }
public string AnswerText { get; set; }
}
I guess I need to use virtual and not the actual object for some reason.. The model looked fine but it seems to confused the update
public class UserAnswer
{
public UserAnswer()
{
this.Question = new Question();
this.User = new ApplicationUser();
}
public int Id { get; set; }
public string UserId { get; set; } // FK to ApplicationUser
public int QuestionId { get; set; } // FK to Question
public string AnswerText { get; set; }
public virtual Question Question { get; set; }
public virtual ApplicationUser User { get; set; }
}

Petapoco can't update with non primary key identity

I am using AspNetIdentity and I have a non primary key column that is an identity auto increment.
[TableName("AspNetUsers")]
[PrimaryKey("Id", autoIncrement = false)]
public class Coach
{
public string Id { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public bool Active { get; set; }
public bool Admin { get; set; }
public int CoachId { get; set; }
}
How can I change my class definition to set CoachId to autoIncrement is false without it being the primary key? I'm using db.Save to save the object.
I just ended up executing a query!
var query = String.Format("UPDATE AspNetUsers SET Active = '{0}' WHERE Id='{1}'",activeStatus,id);

saving reference using ServiceStack ORMLite

I am using ORMLite as my ORM and I am using it with following structure which contains the foreign key relation ship:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
}
As we can see that Order contains the reference to the Item. In DB Order table has a foreign key called ItemId in the table and I have annotated that key in the design view with [Reference] attribute.
I am trying to save the Order with following code:
var order = new Order
{
Item = new Item
{
Id = 3,
Description = "Something"
},
ProUserId = "kunal#kunal.com",
Details = "fdfsdfsd"
};
Db.Save(order,references:true);
I was hoping that ORMLite would pick up the relationship and with ItemID in the Order table but it did not and it did throw following error instead:
Cannot insert the value NULL into column 'ItemId', table 'WebApp.dbo.Order'; column does not allow nulls. INSERT fails.
I tried changing my schema and addred OrderId column in my Item table with reference there and that works fine. But that is not the correct design. Should I make any changes in my code/schema to support this feature?
You still need to provide the foreign key that OrmLite can use to store the relationship, e.g. either on the Child/ForeignKey table:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public int OrderId { get; set; } //Parent Table PK
public string Description { get; set; }
}
Or for 1:1 relationships, can be on the Parent table, e.g:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public int ItemId { get; set; } //Child Table PK
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
}

MVC4 Navigation Properties with composite keys

I have created an MVC4 web application using EF-database-first. The tables have composite keys [ID, Name, EffDate], and no foreign keys defined in the database:
For example, Department partial class:
[MetadataType(typeof(DepartmentMetadata))]
public partial class Department
{
public int DeptID { get; set; }
public string DeptName { get; set; }
public System.DateTime EffDate { get; set; }
public string Status { get; set; }
public string RevenueAccount { get; set; }
}
Department metadata class:
public class DepartmentMetadata
{
[Required]
public int DeptID { get; set; }
[Required]
[Display(Name = "Department Name")]
public string DeptName { get; set; }
[Required]
[Display(Name = "Effective Date")]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", NullDisplayText = "--", ConvertEmptyStringToNull = true)]
public System.DateTime EffDate { get; set; }
[Required]
public string Status { get; set; }
[Display(Name = "Revenue Account")]
[StringLength(10)]
public string RevenueAccount { get; set; }
}
The Allocation table, that refers to the Department table. It also has a composite key [DeptID, ProjectID, BillableUnitID, EffDate]. If I could, I would declare the DeptID field a foreign key ...but I don't control the database, and more importantly I believe T-SQL won't allow foreign keys to part of a composite key:
[MetadataType(typeof(AllocationMetadata))]
public partial class Allocation
{
public int DeptID { get; set; }
public int ProjectID { get; set; }
public int BillableUnitID { get; set; }
public System.DateTime EffDate { get; set; }
public string Status { get; set; }
public decimal Allocation1 { get; set; }
}
This works, but I get a column of DeptID numbers. What I would like to have is a column of department names.
A previous question directed me to virtual navigation properties, so I added them:
[MetadataType(typeof(AllocationMetadata))]
public partial class Allocation
{
[ForeignKey("Department")]
public int DeptID { get; set; }
public int ProjectID { get; set; }
public int BillableUnitID { get; set; }
public System.DateTime EffDate { get; set; }
public string Status { get; set; }
public decimal Allocation1 { get; set; }
public virtual Department Department { get; set; } /* navigation property */
}
The code in the AllocationController for Index is:
public ActionResult Index()
{
return View(db.Allocation.Include(a => a.Department).ToList());
}
When I click on the link to Allocation Index view, I get this error message (after I Stop Debugging):
Server Error in '/' Application.
A specified Include path is not valid. The EntityType
'KC_BillableUnit_TESTModel.Allocation' does not declare a navigation
property with the name 'Department'.
Stack trace
[InvalidOperationException: A specified
Include path is not valid. The EntityType
'KC_BillableUnit_TESTModel.Allocation' does not declare a navigation
property with the name 'Department'.]
System.Data.Objects.Internal.ObjectFullSpanRewriter.ConvertSpanPath(SpanPathInfo
parentInfo, List`1 navPropNames, Int32 pos) +8355128
System.Data.Objects.Internal.ObjectFullSpanRewriter..ctor(DbCommandTree
tree, DbExpression toRewrite, Span span) +256
....continues....
I've tried various combinations of annotations, but all result in the same error.
How can I get my Allocation list to show Department names instead of DeptID numbers?
Off course you can! I think the problem is that your declared the navigation property just in one side (Allocation), however you must declare that at both sides (Department too).
The following must resolve your problem:
[MetadataType(typeof(DepartmentMetadata))]
public partial class Department
{
public Department()
{
this.Allocations = new HashSet<Allocation>();
}
// properties ...
public virtual ICollection<Allocation> Allocations { get; set; }
}