Cannot add a value to a table, error being thrown on a seemingly unrelated table - sql

I am trying to add a value in my checkoutItems table, in the checkoutItems repository I use this method:
public async Task AddItemAsync(unitItem item, int amount, string selectedOptions)
{
var checkoutItem = await _appDbContext.CheckoutItems.SingleOrDefaultAsync(s => s.unitItem.unitItemId == item.unitItemId && s.CheckoutId == _checkout.CheckoutId);
if (checkoutItem == null)
{
checkoutItem = new CheckoutItem
{
CheckoutId = _checkout.CheckoutId,
unitItem = item,
Amount = 1,
selectedOptions = selectedOptions
};
await _appDbContext.CheckoutItems.AddAsync(checkoutItem);
}
else
{
checkoutItem.Amount++;
}
await _appDbContext.SaveChangesAsync();
}
But when this method tries to save the changes I get an error.
SqlException: Cannot insert explicit value for identity column in table 'Categories' when IDENTITY_INSERT is set to OFF
The issue is I am not trying to insert a value in the Categories table. When I check the SQL Server Profiler I see this code is trying to be executed:
exec sp_executesql N'SET NOCOUNT ON;
INSERT INTO [Categories] ([CategoryId], [CategoryName], [Description])
VALUES (#p0, #p1, #p2);
',N'#p0 int,#p1 nvarchar(450),#p2 nvarchar(4000)',#p0=3,#p1=N'Food',#p2=N'Food served by our kitchen'
I have no idea where this is coming from. Everything was working fine until recently. I made no changes to the code and even restored the database to an earlier state to remove the changes (if any) I had made on the database, but no luck. What is causing this and how can I fix it.
The checkoutItems model looks like this:
public class CheckoutItem
{
public int CheckoutItemId { get; set; }
public unitItem unitItem { get; set; }
public int Amount { get; set; }
public string CheckoutId { get; set; }
public string selectedOptions { get; set; }
}
And there are 2 degrees of separation between a checkoutItem and Category where an Item has a category.
Edit
If you comment out the line unitItem = item, in the add AddItemAsync method, seems to go around the issue. So the issue seems to be around adding the unitItem.
I still don't understand why it is adding a category when add a checkout item. The model for the unitItem looks like this:
public class unitItem
{
[Required]
public int unitItemId { get; set; }
[Required]
public string Name { get; set; }
[DisplayFormat(DataFormatString = "{0:n2}")]
public decimal Price { get; set; }
public bool InStock { get; set; }
public DateTime DateModified { get; set; }
public int CategoryId { get; set; }
[Required]
public virtual Category Category { get; set; }
public string ImageUrl { get; set; }
public string Description { get; set; }
public string OptionFormData { get; set; }
}

in your unitItem class add Required attribute to CategoryId not Category
public class unitItem
{
[Required] //here
public int CategoryId { get; set; }
//[Required] //not here
public virtual Category Category { get; set; }
....
then in AddItemAsync method; set NULL category object if CategoryId is bigger than zero
public async Task AddItemAsync(unitItem item, int amount, string selectedOptions)
{
item.Category = null; //be sure item.CategoryId is not zero
.....

Related

How to store value in variable joining two tables

I am still learning SQL, but as I got stuck in these doubt I wrote it here.
Actually I want print a table for list of details which hold a column for "Description". Now this data is retrieving from tblBillDetails. and in tblBillDetails there is no column or field of "Description. Now there is another field which is tblProduct here I have column "Name" & "Id".
So I want something like "Description = tblProduct.Name where tblBillDetails.FunctionId == tblProduct.Id
code--->
.cs file
public class BillDetail
{
public long Id { get; set; }
public long BillId { get; set; }
public int FunctionType { get; set; }
public long FunctionId { get; set; }
public long VatId { get; set; }
public int Quantity { get; set; }
public int Points { get; set; }
public decimal TotalValue { get; set; }
public decimal FreeValue { get; set; }
public DateTime SaleDateTime { get; set; }
public long BalanceId { get; set; }
public decimal RunningBalance { get; set; }
}
repositoy .cs file
public Task<BillDetail> SingleAsync(Guid shardKey, long BillDetailId)
{
return _billDetailDataAccess.SingleAsync(shardKey, BillDetailId);
}
DataAccess .cs file
public async Task<BillDetail> SingleAsync(Guid shardKey, long BillDetailId)
{
string sql = #"SELECT [Id]
,[TenantClientId]
,[BillId]
,[FunctionType]
,[FunctionId]
,[VatId]
,[Quantity]
,[Points]
,[TotalValue]
,[FreeValue]
,[SaleDateTime]
,[BalanceId]
,[RunningBalance]
,[Archived]
FROM [dbo].[tblBillDetail]
WHERE [tblBillDetail].[Id] = #BillDetailId
;";
await _context.OpenConnectionForKeyAsync(shardKey);
return await _context.Connection.QueryFirstOrDefaultAsync<BillDetail>(sql, new { BillDetailId });
}

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; }
}

Ravendb TransformResults showing null values for properties populated with Load()

I have two documents Ticket and MenuItem i have created index with TransformResults but problem is i am getting null value for Loaded document in transform
public class Ticket
{
public int ID { get; set; }
public int ItemId { get; set; }
public string ItemName { get; set; }
public int Price { get; set; }
}
public class MenuItem
{
public int ID { get; set; }
public string ItemName { get; set; }
public string PriceCategory { get; set; }
}
i have created a index like
public class TicketItemGross : AbstractIndexCreationTask<Ticket, TicketItemGross.TicketItemDetails>
{
public class TicketItemDetails
{
public string ID { get; set; }
public string ItemId { get; set; }
public string ItemName { get; set; }
public int Price { get; set; }
public string PriceCategory { get; set; }
}
public TicketItemGross()
{
Map = docs => from doc in docs
select new
{
ID = doc.ID,
ItemId=doc.ItemId,
ItemName=doc.ItemName,
Price=doc.Price
};
TransformResults = (database, docs) => from m in docs
let d = database.Load<MenuItem>(m.ID)
select new
{
ID = m.ID,
ItemId = m.ItemId,
ItemName = m.ItemName,
Price = m.Price,
PriceCategory=d.PriceCategory
};
}
}
and the problem is that when i query data. I get null for PriceCategory but for all other fields i get correct value
here is query
IEnumerable<TicketItemGross.TicketItemDetails> list;
using (var session = store.OpenSession())
{
list = session.Query<TicketItemGross.TicketItemDetails, TicketItemGross>();
}
This is happening because you are using integer IDs. When you call database.Load in your transform, you'll need to manually convert it to a string ID.
database.Load<MenuItem>("MenuItems/" + m.ID)
This is one of several places where Raven gets confused if you use integer or guid IDs. If you use string ids, you won't have this problem.
Also, you might consider using a results transformer instead. They are easier than index transformers, which are now obsolete.

CodeFirst - Update single property

We are using EF5, Code First approach to an MVC4 app that we're building. We are trying to update 1 property on an entity but keep getting errors. Here's what the class looks like which the context created:
public partial class Room
{
public Room()
{
this.Address = new HashSet<Address>();
}
public int RoomID { get; set; }
public Nullable<int> AddressID { get; set; }
public Nullable<int> ProductVersionID { get; set; }
public string PhoneNumber { get; set; }
public string AltPhone { get; set; }
public string RoomName { get; set; }
public string Description { get; set; }
public string Comments { get; set; }
public string Notes { get; set; }
public virtual ICollection<Address> Address { get; set; }
}
Here's our ViewModel for the view:
public class RoomDetailsViewModel
{
//public int RoomID { get; set; }
public string RoomName { get; set; }
public string PhoneNumber { get; set; }
public string AltPhone { get; set; }
public string Notes { get; set; }
public string StateCode { get; set; }
public string CountryName { get; set; }
public string ProductVersion { get; set; }
public int PVersionID { get; set; }
public List<SelectListItem> ProductVersions { get; set; }
public Room Room { get; set; }
}
Here's the Controller Action being called on "Save":
[HttpPost]
public virtual ActionResult UpdateRoom(RoomDetailsViewModel model)
{
var db = new DBContext();
bool b = ModelState.IsValid;
var rooms = db.Rooms;
var rm = rooms.Where(r => r.RoomID == model.Room.RoomID).Single();
//List<Address> address = db.Addresses.Where(a => a.AddressID == rm.AddressID).ToList<Address>();
rm.ProductVersionID = model.PVersionID;
//rm.Address = address;
db.Entry(rm).Property(r => r.ProductVersionID).IsModified = true;
//db.Entry(rm).State = System.Data.EntityState.Modified;
db.SaveChanges();
return View("RoomSaved", model);
}
All this view does is display data and allow the user to change the Product Version (from a SelectList), so, in the Room Entity, all we are updating is the ProductVersionID property, nothing else. We can get the data to display properly but when we click "save", we get this error:
An object of type 'System.Collections.Generic.List`1[[Models.Address,
Web.Mobile.TestSite, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]]' cannot be set or removed from the Value
property of an EntityReference of type 'Models.Address'.
As you can see by the Controller Action, we've tried several different things but all seem to produce this error. I've tried to populate the model.Room.Address collection with an Address, without, but still get this error.
I read this StackOverflow article and this article as well but neither have solved my problem.
ANY help with this would be greatly appreciated!
After hours and hours of digging, turns out that EF did not import some of the PK's for my DB tables. What tipped me off to this was on the Room class, the PK RoomID did not have the [Key] attribute on it. I tried to reimport the table through the edmx but it never came through as a key (even though it's clearly marked PK in the DB). So, to get around it, I created a partial class of my DBContext and override the OnModelCreating event and included the key, like so:
public partial class DBContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Models.Room>().HasEntitySetName("Rooms");
modelBuilder.Entity<Models.Room>().HasKey(r => r.RoomID);
}
}
Once this was done, the Action saved the record as hoped.
I hope this helps someone else!

EF5 Entry not updating

Im trying to update an entry with EF5 with the following actionresult:
[HttpPost]
public ActionResult Edit(int id, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
Reference reference = db.References.Single(x => x.Id == id);
db.Entry(reference).State = EntityState.Modified;
db.SaveChanges();
//Other stuff regarding files/images
return RedirectToAction("Index");
}
return View();
}
Nothing happens. When I debug it, it goes trough the code as everything was fine. But nothing is updated in the db.
Here's the model if needed:
public class Reference
{
public int Id { get; set; }
public string Headline { get; set; }
public string Text { get; set; }
public DateTime Date { get; set; }
public IEnumerable<HttpPostedFileBase> ImageUploadMain { get; set; }
public String MainFileName { get; set; }
public IEnumerable<HttpPostedFileBase> ImageUpload { get; set; }
public virtual ICollection<Image> Files { get; set; }
public virtual ICollection<RefProperties> Properties { get; set; }
public int CategoryId { get; set; }
public virtual Category Category { get; set; }
}
public class Image
{
public int Id { get; set; }
public string FileName { get; set; }
public virtual Reference Reference { get; set; }
}
public class RefProperties
{
public int Id { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual ICollection<Reference> References { get; set; }
}
Not only is the related entries not updated, a main property like "Headline" cant be updated either. What am I doing wrong? Create/delete works fine btw.
As Gert Arnold says, you're not actually modifying any of the Reference values so nothing will be updated. By calling db.Entry(reference).State = EntityState.Modified you're just setting the retrieved entity's state to modified in the ChangeTracker. When you call SaveChanges() it's just going to update the Reference record in the database with the same values that you fetched.
You need to update some of the Reference instance properties to see a change.
[HttpPost]
public ActionResult Edit(int id, IEnumerable<HttpPostedFileBase> files)
{
if (ModelState.IsValid)
{
Reference reference = db.References.Single(x => x.Id == id);
reference.HeaderText = "Changed";
/* No need to interact with the change tracker as the entity is already tracked and you've made a change */
// db.Entry(reference).State = EntityState.Modified;
/* Create/Modify/Update/Delete other entities */
db.SaveChanges();
//Other stuff regarding files/images
return RedirectToAction("Index");
}
return View();
}
Heres what I was looking for:
TryUpdateModel(reference, "");
It has a shitload of overloads. This works though