Entity Framework Newbie - Save to DB - entity-framework-4

I have 3 joined tables; ValidationRun has many Result which has many Error
The following code succeeds in saving to the Result and Error tables but not the ValidationRun.
Can you see the problem please?
private void WriteResultsToDB(SqlDataReader dr, XMLValidator validator)
{
using (var context = new ValidationResultsEntities())
{
var run = new ValidationRun { DateTime = DateTime.Now, XSDPath = this.txtXsd.Text };
//loop through table containing the processed XML
while (dr.Read())
{
var result = new Result
{
AddedDateTime = (DateTime)dr["Added"],
CustomerAcc = (string)dr["CustomerAcc"],
CustomerRef = (string)dr["CustomerRef"]
};
if (this.rdoRequest.Checked)
{
result.XMLMsg = (string)dr["RequestMSG"];
}
else
{
result.XMLMsg = (string)dr["ReplyMSG"];
}
if (validator.Validate(result.XMLMsg))
{
foreach (string error in validator.Errors)
{
result.Errors.Add(new Error { ErrorDescription = error });
}
}
else
{
//validator caught an error
result.Errors.Add(new Error { ErrorDescription = "XML could not be parsed" });
}
if (result.Errors.Count == 0) result.ValidFile = true; else result.ValidFile = false;
context.AddToResults(result);
context.SaveChanges();
}
}

You don't appear to be adding the run to any part of the context. If it were referenced by the result you are adding, perhaps, the change tracker would know it was supposed to be saved, but as it is written it is just some orphaned object that doesn't get attached anywhere.

Related

Create to database using web api

I am trying to insert a new entry in my database using web api. I have two web projects: one is a UI project where all the user interaction will occur and the other is a services project which will handle all interactions with my database.
Below is my post method that will take in form data for creating a new team.
// POST: Api/Team/Create
[HttpPost]
public ActionResult Create(Team team)
{
try
{
if (ModelState.IsValid)
{
HttpEndPointContext httpEndPoint = new HttpEndPointContext()
{
AuthenticationMethod = HttpAuthenticationMethods.None,
Ssl = false,
HttpMethod = HttpMethod.Post,
Path = "localhost:32173/api/team/",
QueryStrings = null,
PayloadData = SerializationHelper.Current.Serialize(team.ToString(), SerializationTypes.Xml)
};
IProcessResult result = HttpConnectionManager.Current.SendMessage(httpEndPoint);
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
And this is my method for dealing with my PayloadStream/PayloadData attribute in the above method:
private void StreamPayload(HttpWebRequest webRequest, HttpEndPointContext httpEndPointContext)
{
if (httpEndPointContext.HttpMethod == new HttpMethod("GET"))
return;
//TODO: FIX MAYBE .... sometimes we want to post body with GET.
//Stream vs string
if (httpEndPointContext.PayloadStream == null)
{
//Wrap with SOAP Envelope and method if defined in SoapDefinition
string data = httpEndPointContext.PayloadData ?? String.Empty;
if (httpEndPointContext.SoapDefinition != null)
{
//If parameters is set, clear existing payload data.
data = String.Empty;
if (httpEndPointContext.SoapDefinition.Parameters != null)
foreach (var parameter in httpEndPointContext.SoapDefinition.Parameters)
{
data += String.Format("<{0}>{1}</{0}>", parameter.Key, parameter.Value);
}
data = String.Format("<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'>" +
"<s:Body><{0} xmlns='{2}'>" +
"{1}</{0}></s:Body></s:Envelope>",
httpEndPointContext.SoapDefinition.SoapMethod, data,httpEndPointContext.SoapDefinition.SoapGlobalKey);
}
byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(data);
httpEndPointContext.PayloadStream = new MemoryStream(byteArray);
}
using (Stream requestStream = webRequest.GetRequestStream())
{
StreamHelper.Current.CopyStreams(httpEndPointContext.PayloadStream, requestStream);
requestStream.Close();
}
}
And the code for getting the server response. I'm currently getting an Internal Server (500) Error. Not sure why.
public IProcessResult SendMessage(HttpEndPointContext httpEndPointContext)
{
HttpWebRequest webRequest = CreateWebRequest(httpEndPointContext);
StreamPayload(webRequest, httpEndPointContext);
IProcessResult result = GetWebResponse(webRequest, httpEndPointContext);
return result;
}
private IProcessResult GetWebResponse(HttpWebRequest webRequest, HttpEndPointContext httpEndPointContext)
{
//Get Response
WebResponse response;
IProcessResult result = new ProcessResult(Statuses.Success);
try
{
response = webRequest.GetResponse();
}
catch (System.Net.WebException ex)
{
//Do exception handling. Still get the response for 500s etc.
result.Error.Exception = ex;
result.Status = Constants.Statuses.FailedUnknown;
result.ResponseCodeDescription = ex.Status.ToString();
result.ResponseCode = ex.Status.ToString();
result.Error.ErrorCode = ex.Status.ToString();
response = ex.Response;
//The error did not have any response, such as DNS lookup.
if (response == null)
return result;
}
try
{
//Get the response stream.
Stream responseData = response.GetResponseStream();
if (responseData == null)
throw new CoreException("No Response Data in GetWebResponse.",
"No Response Data in GetWebResponse. EndPoint:{0}", httpEndPointContext.ToString());
// Open the stream using a StreamReader for easy access.
var reader = new StreamReader(responseData);
// Read the content.
result.ResponseData = reader.ReadToEnd();
}
finally
{
response.Close();
}
result.ResponseCode = ((int)((HttpWebResponse)response).StatusCode).ToString();
result.ResponseCodeDescription = ((HttpWebResponse) response).StatusDescription;
return result;
}
And finally, my method for inserting to the database, found in my services project:
//POST api/controller/5
public IProcessResult Insert(Team team)
{
return TeamBusinessManager.Current.Insert(SecurityManager.Current.ConnectionContext, new Team());
}
I'm confused as to why I'm getting the 500 error. I'm not sure if it's the PayloadData attribute in my POST method or is it something wrong with my method in my services project.

An exception of type 'System.OutOfMemoryException' occurred in itextsharp.dll but was not handled in user code

I am using iTextSharp to create pdf. I have 100k records, but I am getting following exception:
An exception of type 'System.OutOfMemoryException' occurred in
itextsharp.dll but was not handled in user code At the line:
bodyTable.AddCell(currentProperty.GetValue(lst, null).ToString());
Code is:
var doc = new Document(pageSize);
PdfWriter.GetInstance(doc, stream);
doc.Open();
//Get exportable count
int columns = 0;
Type currentType = list[0].GetType();
//PREPARE HEADER
//foreach visible columns check if current object has proerpty
//else search in inner properties
foreach (var visibleColumn in visibleColumns)
{
if (currentType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key) != null)
{
columns++;
}
else
{
//check child property objects
var childProperties = currentType.GetProperties();
foreach (var prop in childProperties)
{
if (prop.PropertyType.BaseType == typeof(BaseEntity))
{
if (prop.PropertyType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key) != null)
{
columns++;
break;
}
}
}
}
}
//header
var headerTable = new PdfPTable(columns);
headerTable.WidthPercentage = 100f;
foreach (var visibleColumn in visibleColumns)
{
if (currentType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key) != null)
{
//headerTable.AddCell(prop.Name);
headerTable.AddCell(visibleColumn.Value);
}
else
{
//check child property objects
var childProperties = currentType.GetProperties();
foreach (var prop in childProperties)
{
if (prop.PropertyType.BaseType == typeof(BaseEntity))
{
if (prop.PropertyType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key) != null)
{
//headerTable.AddCell(prop.Name);
headerTable.AddCell(visibleColumn.Value);
break;
}
}
}
}
}
doc.Add(headerTable);
var bodyTable = new PdfPTable(columns);
bodyTable.Complete = false;
bodyTable.WidthPercentage = 100f;
//PREPARE DATA
foreach (var lst in list)
{
int col = 1;
foreach (var visibleColumn in visibleColumns)
{
var currentProperty = currentType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key);
if (currentProperty != null)
{
if (currentProperty.GetValue(lst, null) != null)
bodyTable.AddCell(currentProperty.GetValue(lst, null).ToString());
else
bodyTable.AddCell(string.Empty);
col++;
}
else
{
//check child property objects
var childProperties = currentType.GetProperties().Where(p => p.PropertyType.BaseType == typeof(BaseEntity));
foreach (var prop in childProperties)
{
currentProperty = prop.PropertyType.GetProperties().FirstOrDefault(p => p.Name == visibleColumn.Key);
if (currentProperty != null)
{
var currentPropertyObjectValue = prop.GetValue(lst, null);
if (currentPropertyObjectValue != null)
{
bodyTable.AddCell(currentProperty.GetValue(currentPropertyObjectValue, null).ToString());
}
else
{
bodyTable.AddCell(string.Empty);
}
break;
}
}
}
}
}
doc.Add(bodyTable);
doc.Close();
A back of the envelope computation of the memory requirements given the data you provided for memory consumption gives 100000 * 40 * (2*20+4) = 167MBs. Well within your memory limit, but it is just a lower bound. I imagine each Cell object is pretty big. If each cell would have a 512 byte overhead you could be well looking at 2GB taken. I reckon it might be even more, as PDF is a complex beast.
So you might realistically be looking at a situation where you are actually running out of memory. If not your computers, then at least the bit C# has set aside for its own thing.
I would do one thing first - check memory consumption like here. You might even do well to try with 10, 100, 1000, 10000, 100000 rows and see up until what number of rows the program works.
You could perhaps try a different thing altogether. If you're trying to print a nicely formatted table with a lot of data, perhaps you could output an HTML document, which can be done incrementally and which you can do by just writing stuff to a file, rather than using a third party library. You can then "print" that HTML document to PDF. StackOverflow to the rescue again with this problem.

breeze observableArray binding - are properties observable?

I have a viewmodel which consists of a list(foreach loop) of DoctorPrices and when clicking on an item in the list it open up a CRUD form on the side. However when i update the values on the CRUD the observableArray that is bound to the foreach is not refreshing? (although the values are updates in the DB correctly)
From my data access module i call the following query.
function getDoctorServices(doctorId) {
var query = breeze.EntityQuery
.from('DoctorPrices')
.where('DoctorID', 'eq', doctorId).orderBy('ListOrder');
return manager.executeQueryLocally(query);
}
In my viewmodel i have the following code:
this.services = ko.computed(function() {
return doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID());
});
services is bound using a foreach loop (not posting here as the code is simple and works)
When i click on a one of the DoctorPrices it gets the data as follows and places it in an observable:
this.selectedPrice = function (data, event) {
self.currentService(data);
self.showEdit(true);
};
I then bind selectPrice to a simple form that has the properties on it to be modified by the user. I then call manager.SaveChanges().
This results in the following problem: the value is being updated correctly but the GUI / Original List that is bound in the foreach is not being updated? Are the properties in breeze not observables? What is the best way to work with something like this.
I thought of a workaround and changing the code with something like this:
doctorList.viewModel.instance.currentDoctorID.subscribe(function() {
self.services([]);
self.services(doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID()));
});
But i feel that clearing the array in that way is sloppy and not the right way of doing things specially with long lists.
Can someone please point me in the right direction on how to bind observableArray properties properly so they are updated?
Additional code my VM Component:
function services() {
var self = this;
this.showForm = ko.observable(false);
this.currentService = ko.observable();
this.services = ko.observableArray(doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID()));
this.title = ko.observable();
doctorList.viewModel.instance.currentDoctorID.subscribe(function() {
self.services([]);
self.services(doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID()));
self.showDetails(false);
});
this.show = function (value) {
self.showForm(value);
};
this.showDetails = ko.observable(false);
this.addNewService = function() {
self.currentService(doctorServices.createService(doctorList.viewModel.instance.currentDoctorID()));
console.log(self.currentService().entityAspect.entityState);
self.showDetails(true);
};
this.showDelete = ko.computed(function() {
if (self.currentService() == null)
return false;
else if (self.currentService().entityAspect.entityState.isDetached()) {
self.title('Add new service');
return false;
} else {
self.title('Edit service');
return true;
}
});
this.deleteService = function() {
self.currentService().entityAspect.setDeleted();
doctorServices.saveChanges();
doctorList.viewModel.instance.currentDoctorID.notifySubscribers();
};
this.closeDetails = function () {
doctorServices.manager.rejectChanges();
doctorList.viewModel.instance.currentDoctorID.notifySubscribers();
self.showDetails(false);
};
this.selectService = function (data, event) {
self.currentService(data);
self.showDetails(true);
};
this.saveChanges = function () {
console.log(self.currentService().entityAspect.entityState);
if (self.currentService().entityAspect.entityState.isDetached()) {
doctorServices.attachEntity(self.currentService());
}
console.log(self.currentService().entityAspect.entityState);
doctorServices.saveChanges();
doctorList.viewModel.instance.currentDoctorID.notifySubscribers();
self.currentService.notifySubscribers();
self.showDetails(true);
};
}
return {
viewModel: {
instance: new services()
},
template: servicesTemplate,
};
Below is my Breeze Data Class:
define('data/doctorServices', ['jquery', 'data/dataManager', 'knockout','mod/medappBase', 'breeze', 'breeze.savequeuing'], function ($, manager, ko,base, breeze, savequeuing) {
var services = ko.observableArray([]);
return {
attachEntity:attachEntity,
getServices: getServices,
services: services,
manager:manager,
getDoctorServices: getDoctorServices,
getServiceById: getServiceById,
createService:createService,
hasChanges: hasChanges,
saveChanges: saveChanges
};
function getServices() {
var query = breeze.EntityQuery.from("DoctorPrices");
return manager.executeQuery(query).then(function (data) {
services(data.results);
}).fail(function (data) {
console.log('fetch failed...');
console.log(data);
});;
}
function getDoctorServices(doctorId) {
var query = breeze.EntityQuery
.from('DoctorPrices')
.where('DoctorID', 'eq', doctorId).orderBy('ListOrder');
var set = manager.executeQueryLocally(query);
return set;
}
function getServiceById(serviceId) {
return manager.createEntity('DoctorPrice', serviceId);
//return manager.getEntityByKey('DoctorPrice', serviceId);
}
function handleSaveValidationError(error) {
var message = "Not saved due to validation error";
try { // fish out the first error
var firstErr = error.innerError.entityErrors[0];
message += ": " + firstErr.errorMessage;
base.addNotify('error', 'Could not save.', message);
} catch (e) { /* eat it for now */ }
return message;
}
function hasChanges() {
return manager.hasChanges();
}
function attachEntity(entity) {
manager.addEntity(entity);
}
function createService(doctorId) {
return manager.createEntity('DoctorPrice', { DoctorPricingID: breeze.core.getUuid(), DoctorID:doctorId }, breeze.EntityState.Detached);
};
function saveChanges() {
return manager.saveChanges()
.then(saveSucceeded)
.fail(saveFailed);
function saveSucceeded(saveResult) {
base.addNotify('success', 'Saved.', 'Your updates have been saved.');
}
function saveFailed(error) {
var reason = error.message;
var detail = error.detail;
if (error.innerError.entityErrors) {
reason = handleSaveValidationError(error);
} else if (detail && detail.ExceptionType &&
detail.ExceptionType.indexOf('OptimisticConcurrencyException') !== -1) {
// Concurrency error
reason =
"Another user, perhaps the server, " +
"may have deleted one or all of the settings." +
" You may have to restart the app.";
} else {
reason = "Failed to save changes: " + reason +
" You may have to restart the app.";
}
console.log(error);
console.log(reason);
}
}
});
Please note this is my frist attempt at both a data class and VM. At the moment i am relying heavily on clearing the array ([]) and using notifySubscribers to make the array refresh :(
I bet you're missing an observable somewhere. I can't tell because you keep hopping from property to property whose definition is not shown.
For example, I don't know how you defined this.currentService.
I'm confused by this:
this.services = ko.computed(function() {
return doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID());
});
Why is it a ko.computed? Why not just make it an observable array.
self.service = ko.observableArray();
// ... later replace the inner array in one step ...
self.service(doctorServices.getDoctorServices(
doctorList.viewModel.instance.currentDoctorID()));
I urge you to follow the observability trail, confident that your Breeze entity properties are indeed observable.
vm.selectedPrice = ko.dependentObservable(function () {
return doctorServices.getDoctorServices(doctorList.viewModel.instance.currentDoctorID());
}, vm);
vm is ur model on which u applied bindings , try this it will work.

Entity Framework 5 - read a record then delete it in loop

I am having issues with my application. I have a db table for a print queue. When I read from that table in a loop, once I add that record to the view model, I then want to delete it from the database...this would be the most efficient way to do it, but EF barks:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker.
I've tried using multiple contexts... but that didn't seem to work either. I've seen articles like Rick Strahl's, but frankly it was above my level of understanding, and not exactly sure if it helps my issue here and seemed quite an in depth solution for something as simple as this.
Is there a simple way to accomplish what I am trying to achieve here?
Here is my code:
public List<InventoryContainerLabelViewModel> CreateLabelsViewModel(int intFacilityId)
{
var printqRep = new Repository<InventoryContainerPrintQueue>(new InventoryMgmtContext());
var printqRepDelete = new Repository<InventoryContainerPrintQueue>(new InventoryMgmtContext());
IQueryable<InventoryContainerPrintQueue> labels =
printqRep.SearchFor(x => x.FacilityId == intFacilityId);
List<InventoryContainerLabelViewModel> labelsViewModel = new List<InventoryContainerLabelViewModel>();
if (labels.Count() > 0)
{
//Get printq record
foreach (InventoryContainerPrintQueue label in labels)
{
IEnumerable<InventoryContainerDetail> icDtls =
label.InventoryContainerHeader.InventoryContainerDetails;
//Get print details
foreach (InventoryContainerDetail icDtl in icDtls)
{
labelsViewModel.Add(new InventoryContainerLabelViewModel()
{
...
populate view model here
}
);//Add label to view model
} //for each IC detail
//Delete the printq record
printqRepDelete.Delete(label); <======== Error Here
} //foreach label loop
}//label count > 0
return labelsViewModel.ToList();
}
In the end, I added a column to the printq table for status, then in the the loop updated it to processed, then called a separate method to delete it.
public List<InventoryContainerLabelViewModel> CreateLabelsViewModel(int intFacilityId)
{
InventoryMgmtContext dbContext = new InventoryMgmtContext();
var printqRep = new Repository<InventoryContainerPrintQueue>(dbContext);
IEnumerable<InventoryContainerPrintQueue> unprintedPrtqRecs =
printqRep.SearchFor(x => x.FacilityId == intFacilityId && x.Printed == false);
List<InventoryContainerLabelViewModel> labelsViewModel = new List<InventoryContainerLabelViewModel>();
if (unprintedPrtqRecs.Count() > 0)
{
//Get printq record
foreach (InventoryContainerPrintQueue unprintedPrtqRec in unprintedPrtqRecs)
{
IEnumerable<InventoryContainerDetail> icDtls =
unprintedPrtqRec.InventoryContainerHeader.InventoryContainerDetails;
//Get container details to print
foreach (InventoryContainerDetail icDtl in icDtls)
{
labelsViewModel.Add(new InventoryContainerLabelViewModel()
{
...
}
);//Get IC details and create view model
} //for each IC detail
unprintedPrtqRec.Printed = true;
printqRep.Update(unprintedPrtqRec, unprintedPrtqRec, false);
} //foreach label loop
//Commit updated to Printed status to db
dbContext.SaveChanges();
}//label count > 0
return labelsViewModel;
}
public ActionConfirmation<int> DeletePrintQRecs(int intFacilityId)
{
InventoryMgmtContext dbContext = new InventoryMgmtContext();
var printqRep = new Repository<InventoryContainerPrintQueue>(dbContext);
IEnumerable<InventoryContainerPrintQueue> printedPrtqRecs =
printqRep.SearchFor(x => x.FacilityId == intFacilityId && x.Printed == true);
foreach (InventoryContainerPrintQueue printedPrtqRec in printedPrtqRecs)
{
//Delete the printq record
printqRep.Delete(printedPrtqRec, false);
}
//Save Changes on all deletes
ActionConfirmation<int> result;
try
{
dbContext.SaveChanges();
result = ActionConfirmation<int>.CreateSuccessConfirmation(
"All Label Print Q records deleted successfully.",
1);
}
catch (Exception ex)
{
result = ActionConfirmation<int>.CreateFailureConfirmation(
string.Format("An error occured attempting to {0}. The error was: {2}.",
"delete Label Print Q records",
ex.Message),
1
);
}
return result;
}

How to reuse j2me kxml parser?

I am useing kxml parser for my j2me application. I am reading the file from phone memory and parsing the xml file to display the data(have various level of filter). On each filter i need to read the data from this file. For first time i created the parser and every time i re-assign this parser1(reference-original) to the paerser2(used to parse data). For first time i got the correct answer, but second time i haven't got the file content it shows null as data.
Here is my code:
FileConnection fc = (FileConnection)Connector.open(rmsObj.rmsData.elementAt(0).toString());
InputStream in = fc.openInputStream();
InputStreamReader is = new InputStreamReader(in);
commonAppObj.externParser = new XmlParser(is);
commonAppObj class file.
protected void fileread() {
try {
if(externParser != null){
parser = externParser;
fileparser(parser);
}else{
InputStream in = this.getClass().getResourceAsStream(this.dataBase);
InputStreamReader is = new InputStreamReader(in);
parser = new XmlParser(is);
fileparser(parser);
}
} catch (IOException ioe) {
} finally {
parser = null;
}
}
private void fileparser(XmlParser parser){
try {
ParseEvent event = null;
dataflag = 0;
dataflagS = 0;
System.out.println("findtags = " + findtags);
while (((event = parser.read()).getType() != Xml.END_DOCUMENT) && (dataflag != 1)) {
if (event.getType() == Xml.START_TAG) {
String name = event.getName();
if (name != null && name.equals(findtags)) {
dataflag = 0;
parseAddressTag(parser);
}
name = null;
}
event = null;
}
} catch (IOException ioe) {
} finally {
parser = null;
}
}
}
If your InputStream returns true in a call to markSupported you may reset it at the end of fileparser method, but first you need to call mark right after creating it.
if (in.markSupported()) {
in.mark(in.available());
}

Resources