PUT does not insert object in SQL Server - c#

I'm having a problem with Web API where I want to create a new object in SQL Server.
The PUT method is used to update an expensenote. An expensenote contains dailyexpensenotes. A dailyexpensenote contains individualexpenses.
In the GUI, a user that edits his expensenote can:
Fill in an empty individualexpense with value > 0 (Creates a new individualexpense)
Change an existing individualexpense (Updates the existing individualexpense)
Clear an individualexpense/change value to 0 (Deletes the existing individualexpense)
After this the user clicks save and the entire expensenote is sent by ajax call to the web service. Nr 2 and Nr 3 are working as desired but the Nr 1 doesn't work and gives no error.
PUT method
// PUT api/expenses/5
public void Put(int id, [FromBody]Expensenote exUpdate)
{
expensenote ex = (from e in db.expensenotes
where e.ID == id
select e).FirstOrDefault();
if (ex == null)
{
//return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Request was not found.");
}
else
{
foreach (Expensenotedaily d in exUpdate.dailyExpenses)
{
var daily = ex.expensenotedailies.SingleOrDefault(da => da.ID == d.ID);
daily.city = d.city;
daily.dailyallowance = d.dailyallowance;
foreach (Expenseindividual i in d.individualExpenses)
{
expenseindividual individual = daily.expenseindividuals.SingleOrDefault(ind => ind.ID == i.ID);
if (i.value == 0)
{
if (!(individual == null))
{
db.expenseindividuals.Remove(individual);
}
}
else
{
if (!(individual == null))
{
individual.value = i.value;
}
else
{
expenseindividual newInd = db.expenseindividuals.Create();
newInd.typecode_ID = i.expensetypeID;
newInd.daily_ID = daily.ID;
newInd.typecode = db.typecodes.SingleOrDefault(t => t.ID == i.expensetypeID);
newInd.expensenotedaily = daily;
newInd.value = i.value;
newInd.creditcard = false;
db.expenseindividuals.Add(newInd);
//SOLUTION: db.SaveChanges();
}
}
}
}
db.SaveChanges();
}
}
expenseindividual datamodel class
public partial class expenseindividual
{
public expenseindividual()
{
this.supplementalinfoes = new HashSet<supplementalinfo>();
}
public int ID { get; set; }
public double value { get; set; }
public bool creditcard { get; set; }
public int daily_ID { get; set; }
public int typecode_ID { get; set; }
public virtual expensenotedaily expensenotedaily { get; set; }
public virtual typecode typecode { get; set; }
public virtual ICollection<supplementalinfo> supplementalinfoes { get; set; }
}
When I debug I see that all attributes are passed correctly.
Using newInd = new expenseindividual() instead of Create() doesn't fix the problem.
I tried setting the expenseindividual.ID manually and this makes the insert work but it must auto increment and auto increment is enabled.
So I'm really wondering what causes the problem here and how I can fix it?

If I understand you correctly, you are trying to insert a new expense note into the database when one does not already exist?
Firstly... this code currently ignores expense notes that do not already exist in the database...
expensenote ex = (from e in db.expensenotes
where e.ID == id
select e).FirstOrDefault();
if (ex == null)
{
//return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Request was not found.");
}
else
{
ex will always be null when you pass an id of an expense note that does not already exist inside of the database, therefore no code will be run.
The convention is that typically PUT is always used to update a record, POST is used instead when trying to create one but thats up to you.
You need to implement your logic to create a new record within the if statement, replacing the commented out return statement.

Related

SQLLITE-Xamarin Form - How to check if a value already exist

I looking to check if a value already exists, if exists return true if not false. However, I may be missing something on my logic because is always returning null even if the value exists
sample
public bool ExistPref(int userid)
{
var result = prefDB.db.Table<notificationsPreferences>().Where(t => t.UserId == userid).FirstOrDefault();
Console.WriteLine("user exist "+result+userid);
return result != null;
}
and if the user exist
I would like to update his record otherwise insert the new values
public int UpdateNotifications(notificationsPreferences item)
{
if (item.UserId != 0)
{
return prefDB.db.Update(item);
}
else
{
return prefDB.db.Insert(item);
The issue is here ** the Id comes inside the object item, however for some reason doesn't save the 4 digits id, what gets saved is for example 4 which I assumed is the times I add this item?/ that's why my result is always false because it is not saving the real id .
}
}
use Any
return prefDB.db.Table<notificationsPreferences>().Any(t => t.UserId == userid);
if the user exist I would like to update his record otherwise insert the new values
If you want to insert new record or update record into sqlite, you can take a look the following code:
private void insertorupdate(User model)
{
var data = _SQLiteConnection.Table<User>();
var d1 = data.Where(x => x.userId == model.userId).FirstOrDefault();
if (d1 == null)
{
_SQLiteConnection.Insert(model);
Console.WriteLine("Sucessfully Added");
}
else
{
Console.WriteLine("Already Mail id Exist");
_SQLiteConnection.Update(model);
}
}
public class User
{
[PrimaryKey, AutoIncrement]
public int userId { get; set; }
public string userName { get; set; }
public string password { get; set; }
}

Entity Framework - New child entities not added to database on saving parent entity (only in production environment)

I am facing a weird issue in an application. I have the following code which updates a parent entity and add new child entities.
Item item = db.Items.Find(Id);
if (newSubItems.Count() > 0)
{
newSubItems.ForEach(x =>
{
var subItem = new SubItem();
subItem.Name = x.Name;
item.SubItems.Add(subItem);
});
}
item.ModifiedAt = DateTime.Now;
item.ModifiedBy = UserId;
db.Entry(item).State = EntityState.Modified;
using (var s = db.Database.BeginTransaction(isolationLevel: IsolationLevel.RepeatableRead))
{
await db.SaveChangesAsync();
s.Commit();
logger.info("Updated successfully.");
}
This code is working fine in my local environment. If I supply new sub-items, those are added successfully to the respective table.
The models are given below.
public partial class Item
{
public Item()
{
this.SubItems = new HashSet<SubItem>();
}
public int Id { get; set; }
public DateTime ModifiedAt { get; set; }
public int ModifiedBy { get; set; }
public virtual ICollection<SubItem> SubItems { get; set; }
}
public partial class SubItem
{
public int Id { get; set; }
public string Name { get; set; }
public int ItemId { get; set; }
public Item Item { get; set; }
}
However this is not working in my production environment as expected. Parent entity is updated, but new child entities are not added if there are no existing child entities. I checked the logs and I can see that "Updated successfully" is logged. If there is at-least 1 child entity for the parent, then new child entities are added successfully.
So now as a work around in production environment, I am re-adding the sub-items again after the first save operation using the below code.
int subItemsCount = db.SubItems.Where(a => a.ItemId == item.Id).Count();
if (subItemsCount == 0 && newSubItems.Count() > 0)
{
logger.info(string.Format("Sub-items are not added for Id - {0}. Adding those again.", item.Id));
newSubItems.ForEach(x =>
{
var subItem = new SubItem();
subItem.Name = x.Name;
subItem.ItemId = item.Id;
db.SubItems.Add(subItem);
});
await db.SaveChangesAsync();
logger.info(string.Format("Sub-items re-added successfully for Id - {0}.", item.Id));
}
Now at looking the logs from production environment, I can see that the message "Sub-items are not added for Id" is logged many times and sub-items are added successfully in the second save operation.
Wondering if any one know the reason for this weird behavior in specific environment alone.
In your first approach you should check if item.SubItems for null before doing item.SubItems.Add() on it.
If it is null then initialize like item.SubItems = new ICollection<SubItem>();
In your second approach,in this code block you are not assigning ItemId
newSubItems.ForEach(x =>
{
var subItem = new SubItem();
subItem.Name = x.Name;
subItem.ItemId = item.Id;/* missing line*/
db.SubItems.Add(subItem);
});

Create or update if item exist

I have a create form where if the specific Medicine exist, its number of supply will update or added with the new entry however if the specific Medicine doesn't exist, it will create a new batch of data.
Im having trouble at understanding how update works in MVC.
Here is the error:
Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded.
Here is my controller:
public ActionResult Create([Bind(Include = "SupplyID,MedicineID,Expiration,NumberOfSupply")] Supply supply)
{
if (ModelState.IsValid)
{
bool supplyExsist = db.Supplies.Any(x => x.Expiration == supply.Expiration && x.MedicineID == supply.MedicineID);
if (supplyExsist)
{
var currentSupply = (from x in db.Supplies //get current supply
where x.MedicineID == supply.MedicineID
&& x.Expiration == supply.Expiration
select x.NumberOfSupply).First();
db.Entry(supply).State = EntityState.Modified;
supply.NumberOfSupply = currentSupply + supply.NumberOfSupply;
db.SaveChanges();
return RedirectToAction("Index");
}
else
{
db.Supplies.Add(supply);
db.SaveChanges();
return RedirectToAction("Index");
}
}
ViewBag.MedicineID = new SelectList(db.Medicines, "MedicineID", "MedicineName", supply.MedicineID);
return View(supply);
}
Model:
public class Supply
{
[Key]
public int SupplyID { get; set; }
[ForeignKey("Medicine")]
public int MedicineID { get; set; }
public Medicine Medicine { get; set; }
[DataType(DataType.Date)]
public DateTime Expiration { get; set; }
[Display(Name = "Quantity")]
[Range(1, int.MaxValue, ErrorMessage = "The value must be greater than 0")]
public int NumberOfSupply { get; set; }
}
just try this
db.Supplies.AddOrUpdate(h => h.medicineID,supply));
it will check if there is a row with the same medicine ID in db if not it adds a new one else it updates it
You should change your if block with following :
if (supplyExsist)
{
var currentSupply = (from x in db.Supplies //get current supply
where x.MedicineID == supply.MedicineID
&& x.Expiration == supply.Expiration
select x.NumberOfSupply).First();
db.Supplies.Attach(supply);
db.Entry(supply).State = EntityState.Modified;
supply.NumberOfSupply = currentSupply + supply.NumberOfSupply;
db.SaveChanges();
return RedirectToAction("Index");
}

LINQ Error with DTO

I'm seeing a weird issue and I think I'm missing something. The DTO doesn't seem to get populated when returned. Only the properties that are being init in the LINQ query get set, the ones that are being set in ParseJobResultsXml do not get setup as seen in the DEBUG output.
The DTO is being setup in a LINQ query, something like this:
public class JobResultDTO
{
[Key]
public string Id { get; set; }
public string Created { get; set; }
public string Finished { get; set; }
public string Status { get; set; }
public string PlantLink { get; set; }
public IEnumerable<string> Messages { get; set; }
public string JobType { get; set; }
}
private void ParseJobResultXml(string jobResultXml, JobResultDTO jobDto)
{
try
{
var xmlElement = XElement.Parse(jobResultXml);
if (xmlElement != null)
{
jobDto.Finished = xmlElement.Element("Date").Value;
jobDto.Status = xmlElement.Element("Status").Value;
jobDto.PlantLink = xmlElement.Element("PlantLink").Value;
jobDto.Messages = xmlElement.Element("Messages").Elements("Message").Select(m => m.Value);
}
}
catch { }
}
var jobsAndResults = _context.Jobs.Where(j => j.JobType == jobOpenPlant || j.JobType == jobNormSite)
.AsEnumerable()
.Where(j => JobResultXmlHelper.JobBelongsToUser(j.JobResult, userLogin))
.OrderByDescending(j => j.JobCreated)
.Select(j => new
{
Result = j.JobResult,
Dto = new JobResultDTO
{
Id = j.Id.ToString(),
JobType = j.JobType,
Created = (j.JobCreated ?? DateTime.Now).ToString()
}
});
foreach (var j in jobsAndResults)
{
ParseJobResultXml(j.Result, j.Dto);
DumpDTO(j.Dto); //I see it set up correctly here
}
jobs.AddRange(jobsAndResults.Select(j => j.Dto));
DumpDTO(jobs.ElementAt(0)); //Now only the Key property is set
return jobs;
This is Debug output I'm seeing on the server for the two DEBUG lines
On Server...
Id: 51a8d041-5dff-4849-9651-9fb2fe89816a Status: Finished
Catalog - Updated 0 record(s) successfully:
Model - Updated 0 record(s) successfully:
On Server...
Id: 51a8d041-5dff-4849-9651-9fb2fe89816a Status:
As you can see the 2nd one has no entry for Status coln. Any ideas why this is happening?
I think your code is correct, but you don't have waiting time.
I didn't see any LoadOperation in your syntax.
Your code will work in WPF, but not in SilverLight.
*Update:*Try
foreach (var j in jobsAndResults)
{
ParseJobResultXml(j.Result, j.Dto);
DumpDTO(j.Dto); //I see it set up correctly here
jobs.Add(j.Dto);
}

Optimizing simple usage of Linq in C#

I have replicated a stripped-down version of my code that has recently been re-written to use linq to access the database.
However, in my opinion, the linq is really simple and could probably be optimized quite a bit, especially around line 90 where there is a linq statement inside a foreach loop.
It'd be really helpful to see how someone else would go about writing this simple task using linq. Thanks in advance! Below is a snippet of my source code.
// Model objects - these are to be populated from the database,
// which has identical fields and table names.
public class Element
{
public Element()
{
Translations = new Collection<Translation>();
}
public int Id { get; set; }
public string Name { get; set; }
public Collection<Translation> Translations { get; set; }
public class Translation
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Language Lang { get; set; }
}
}
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
// Stripped-down functions for adding and loading Element
// objects to/from the database:
public static class DatabaseLoader
{
// Add method isn't too bulky, but I'm sure it could be optimised somewhere.
public static void Add(string name, Collection<Translation> translations)
{
using (var db = DataContextFactory.Create<ElementContext>())
{
var dbElement = new Database.Element()
{
Name = name
};
db.Elements.InsertOnSubmit(dbElement);
// Must be submit so the dbElement gets it's Id set.
db.SubmitChanges();
foreach (var translation in translations)
{
db.Translations.InsertOnSubmit(
new Database.Translation()
{
FK_Element_Id = dbElement.Id,
FK_Language_Id = translation.Lang.Id,
Title = translation.Title,
Content = translation.Content
});
}
// Submit all the changes outside the loop.
db.SubmitChanges();
}
}
// This method is really bulky, and I'd like to see the many separate linq
// calls merged into one clever statement if possible (?).
public static Element Load(int id)
{
using (var db = DataContextFactory.Create<ElementContext>())
{
// Get the database object of the relavent element.
var dbElement =
(from e in db.Elements
where e.Id == id
select e).Single();
// Find all the translations for the current element.
var dbTranslations =
from t in db.Translations
where t.Fk_Element_Id == id
select t;
// This object will be used to buld the model object.
var trans = new Collection<Translation>();
foreach (var translation in dbTranslations)
{
// Build up the 'trans' variable for passing to model object.
// Here there is a linq statement for EVERY itteration of the
// foreach loop... not good (?).
var dbLanguage =
(from l in db.Languages
where l.Id == translation.FK_Language_Id
select l).Single();
trans.Add(new Translation()
{
Id = translation.Id,
Title = translation.Title,
Content = translation.Content,
Language = new Language()
{
Id = dbLanguage.Id,
Name = dbLanguage.Name,
Code = dbLanguage.Code
}
});
}
// The model object is now build up from the database (finally).
return new Element()
{
Id = id,
Name = dbElement.Name,
Translations = trans
};
}
}
}
Using some made-up constructors to oversimplify:
public static Element Load(int id)
{
using (var db = DataContextFactory.Create<ElementContext>())
{
var translations = from t in db.Translations
where t.Fk_Element_Id == id
join l in db.Languages on t.FK_Language_Id equals l.Id
select new Translation(t, l);
return new Element(db.Elements.Where(x => x.Id == id).Single(), translations);
}
}
First thing I don't like in here is all the "new Translation() { bla = bla } because they're big blocks of code, I would put them in a method where you hand them the objects and they return the new for you.
Translations.InsertOnSubmit(CreateDatabaseTranslation(dbElement, translation));
and
trans.Add(CreateTranslationWithLanguage(translation, dbLanguage));
etc, wherever you have code like this, it just muddles the readability of what you're doing in here.

Categories