how to shorten this piece of C# object Oriented code? - c#

this is my createcustomer function which returns a customer object to the caller,
getCustomerDetail returns a datatable which then populates the customer object properties with the values. Problem is whenever there's a change in the object, i have to modify this again, how do I solve this problem so that I only need to change in the Customer object and it saves my work of modifying the entire codes?
public Objects.Customer createCustomer()
{
DataTable dt = Database.Master.Customer.getCustomerDetail(objCustomer.Custcode);
objCustomer.Billaddress1 = dt.Rows[0]["Billaddress1"].ToString();
objCustomer.Billaddress2 = dt.Rows[0]["Billaddress2"].ToString();
objCustomer.Billaddress3 = dt.Rows[0]["Billaddress3"].ToString();
objCustomer.Billcontact = dt.Rows[0]["Billcontact"].ToString();
objCustomer.Billfaxno = dt.Rows[0]["Billfaxno"].ToString();
objCustomer.Billpostalcode = dt.Rows[0]["Billpostalcode"].ToString();
objCustomer.Billremarks = dt.Rows[0]["Billremarks"].ToString();
objCustomer.Billtelno = dt.Rows[0]["Billtelno"].ToString();
objCustomer.Custcode = dt.Rows[0]["Custcode"].ToString();
objCustomer.Custname = dt.Rows[0]["Custname"].ToString();
objCustomer.Doout = dt.Rows[0]["Doout"].ToString();
objCustomer.Douom = dt.Rows[0]["Douom"].ToString();
objCustomer.Inuom = dt.Rows[0]["Inuom"].ToString();
objCustomer.Location = dt.Rows[0]["Location"].ToString();
objCustomer.Outremarks1 = dt.Rows[0]["Outremarks1"].ToString();
objCustomer.Outremarks2 = dt.Rows[0]["Outremarks2"].ToString();
objCustomer.Outremarks3 = dt.Rows[0]["Outremarks3"].ToString();
objCustomer.Pacout = dt.Rows[0]["Pacout"].ToString();
objCustomer.Pacuom = dt.Rows[0]["Pacuom"].ToString();
objCustomer.Perout = dt.Rows[0]["Perout"].ToString();
objCustomer.Peruom = dt.Rows[0]["Peruom"].ToString();
objCustomer.Shipaddress1 = dt.Rows[0]["Shipaddress1"].ToString();
objCustomer.Shipaddress2 = dt.Rows[0]["Shipaddress2"].ToString();
objCustomer.Shipaddress3 = dt.Rows[0]["Shipaddress3"].ToString();
objCustomer.Shipcontact = dt.Rows[0]["Shipcontact"].ToString();
objCustomer.Shipfaxno = dt.Rows[0]["Shipfaxno"].ToString();
objCustomer.Shippostalcode = dt.Rows[0]["Shippostalcode"].ToString();
objCustomer.Shipremaks = dt.Rows[0]["Shipremaks"].ToString();
objCustomer.Shiptelno = dt.Rows[0]["BilladdresShiptelnos1"].ToString();
objCustomer.Shortname = dt.Rows[0]["Shortname"].ToString();
return objCustomer;
}

Some ideas:
Use an Object Relational Model (ORM) tool like Entity Framework or NHibernate
Use a tool like CodeSmith Generator to automatically generate this code for you
Use AutoMapper and Reflection to hydrate your object

You can use Auotamapper.
AutoMapper.Mapper.CreateMap<IDataReader, Objects.Customer>();
var results = AutoMapper.Mapper.Map<IDataReader, IList<Objects.Customer>>(dt.CreateDataReader());

Related

Ramifications of using a stored procedure as a returned object as opposed to using a foreach to populate a data model?

Here are two examples of methods, the first one uses a foreach statement to populate a data model
public List<TheOrderSummary> GetTheOrderSummaryByID(int id)
{
ExoEntities = new ExoEntities();
List<TheOrderSummary> lst = new List<TheOrderSummary>();
foreach(var a in query)
{
lst.Add(new TheOrderSummary
{
OrderDetailID = a.OrderDetailID,
OrderHeaderID = a.OrderHeaderID,
ItemSeq = a.ItemSeq,
MaterialID = a.MaterialID,
Description = a.Description,
DWidth = a.DWidth,
DLength = a.DLength,
MaterialArea = a.MaterialArea.ToString(),
MaterialDetail = a.MaterialDetail,
DHeight = a.DHeight,
PurchUnitOfMeasure = a.PurchUnitOfMeasure,
SellUnitOfMeasure = a.SellUnitOfMeasure,
MaterialCategory = a.MaterialCategory,
MaterialType = a.MaterialType,
MaterialSubType = a.MaterialSubType,
ColorID = (int)a.ColorID,
Color = a.Color,
MaterialPrice = a.MaterialPrice,
MaterialCost = a.MaterialCost,
MaterialLocationID = (int)a.MaterialLocationID,
MaterialLocation = a.MaterialLocation,
LaborPrice = a.LaborPrice,
LaborCost = a.LaborCost,
VendorID = (int)a.VendorID,
VendorName = a.VendorName,
Size = a.Size,
Height = (decimal)a.Height,
Length = (decimal)a.Length,
Width = (decimal)a.Width,
PurchaseQuantity = (decimal)a.PurchaseQuantity,
SellQuantity = (decimal)a.SellQuantity,
TotalFootage = (decimal)a.TotalFootage,
GeneratedItemInd = (int)a.GeneratedItemInd,
ExtendedMaterialPrice = (decimal)a.ExtendedMaterialPrice,
ExtendedLaborCost = (decimal)a.ExtendedLaborCost,
ExtendedMaterialCost = (decimal)a.ExtendedMaterialCost
});
}
return lst;
}
and this one uses a stored procedure to return an object
public List<usp_GetTheOrderDetails_Result> GetTheOrderSummaryByID(int id)
{
ExoEntities = new ExoEntities();
var query = ExoEntities.usp_GetTheOrderDetails(id);
return query.ToList();
}
Both of these are in a DAL and the method that could call either one of these is a JSONResult, both of these can be used to populate a grid. What ramifications would using the second type be down the road as opposed to the first one? They both return the exact same thing, from the looks of it on a performance level, without doing the numbers, the second one would be faster
The pain that is introduced by returning the result directly is that you get a "hard-wired" dependency on the information contract between the consumer and the underlying data provider. If you make a change to the underlying data structure, you must update the client at the same time (which may come with various degrees of pain).
If you instead go with your first option, you encapsulate the knowledge of the underlying information structure into this layer, and may use that to map between the old and new contracts, thereby decoupling the direct dependency between the client and the data provider.
So yes, the second option might bit a tad faster (even though that really should be marginal), but the first one is likely to give you much less pain when it comes to maintaining code and deployments in the longer run.

Dealing with OutOfMemory Exception

Is there a proper way to deal with Out Of Memory Exceptions while looping through a large list and adding objects from that list? What is the proper way to go about doing this? I have a large Linq query that returns around 600K items. I then go through each item and add it to an object. The code is below.
static void Main(string[] args)
{
GrabData();
}
public static void GrabData()
{
decimal? TotalNetClaim = 0;
using (var Context = new VSCMeSnapEntities())
{
List<DriveTimeObject> DataFile = new List<DriveTimeObject>();
DriveTimeObject DT = new DriveTimeObject();
DateTime ParamDate = new DateTime(2015, 05, 30);
List<viewDriveTimeFileDump> DataQuery = new List<viewDriveTimeFileDump>();
DataQuery = (from z in Context.viewDriveTimeFileDumps select z).ToList();
foreach (var item in DataQuery)
{
decimal? AmountChargedParts = DT.GetAmountChargedParts(item.chrComponSts.Trim(), item.mnsTotalParts);
decimal? AmountChargedPartsTax = DT.GetAmountChargedPartsTax(item.chrComponSts.Trim(), item.mnsTotalPartTax);
decimal? AmountChargedLabor = DT.GetAmountChargedLabor(item.chrComponSts.Trim(), item.mnsTotalLabor);
decimal? AmountChargedLaborTax = DT.GetAmountChargedLaborTax(item.chrComponSts.Trim(), item.mnsTotalLaborTax);
int? DaysOut = DT.GetDaysOutClaim(item.intRepairFacilCode, item.dtmContPurchDate, item.dtmReported);
long? MilesOut = DT.GetMilesOutClaim(item.intRepairFacilCode, item.inbIncurMiles, item.inbOrigMiles);
decimal? deductible = DT.GetDeductible(item.chrContSts, item.mnsDeduct);
decimal? netClaim = DT.GetNetClaim(item.chrComponSts.Trim(), item.mnsTotalParts, item.mnsTotalPartTax, item.mnsTotalLabor, item.mnsTotalLaborTax, item.mnsDeduct);
DataFile.Add(new DriveTimeObject
{
DealerNumber = item.chrDlrNum,
VSCName = item.chvVSCName,
IcLocationNumber = item.IcLocationNumber,
IcRegion = item.IcRegion,
Identifier = item.chrIdentifier,
ContractNumber = item.chrContNum,
VIN = item.chrVIN,
CoverageCode = item.CvgCode,
ClaimNum = item.intClaimNum,
OriginalMiles = item.inbOrigMiles,
ContractPurchaseDate = item.dtmContPurchDate,
IncurMiles = item.inbIncurMiles,
DateReported = item.dtmReported,
DaysOutClaim = DaysOut,
MilesOut = MilesOut,
RepairFacilityNumber = item.intRepairFacilCode,
FacilityName = item.chvFacilityName,
ZipFive = item.chrZipFive,
FacilityAdvisor = item.chrFacilAdvisor,
ComponentStatus = item.chrComponSts,
ComponentStatusWord = item.ComponDesc,
ComponentCode = item.chrComponCode,
StatusMasterDescription = item.MasterDesc,
ComponentDescription = item.chvComponDesc,
Parts = AmountChargedParts,
PartsTax = AmountChargedPartsTax,
Labor = AmountChargedLabor,
LaborTax = AmountChargedLaborTax,
Deductible = deductible,
NetClaim = netClaim,
CarrierCode = item.intCarrierCode,
NetworkStatus = item.NetworkStatus,
AddOn = item.chrAddOn,
ETCDate = item.ETC,
ATCDate = item.ATC,
LaborTime = item.reaLaborTime,
PaidDate = item.dtmPdDate,
PaymentID = item.intPaymentID,
BatchNumber = item.intBatchNum
});
TotalNetClaim += netClaim;
}
Context.Dispose();
}
Console.WriteLine(TotalNetClaim);
Console.ReadKey();
}
I run out of memory during the foreach loop and I was wondering how I should go about adjusting my code to make this work.
The way to prevent out of memory is to not run out of memory. Which means you need to get rid of objects you don't need.
Without learning more of your use case, it is hard to suggest the fix. Regardless of that, it's bad practice to have so many objects in memory that you run out and crash. Only keep in memory what you need.
One fix is to not use RAM memory, and instead use hard drive memory. Ex: You can write those objects to a database and get rid of them, so you don't keep them around. Considering you have 600k objects, you could do these in batches of 10k/25k records. Then when you need the objects, you can query them. If you need to do calculations with all the objects, I would recommend doing those operations using SQL queries.
You are creating a new DriveTimeObject and storing it in a List<DriveTimeObject> called DataFile. Assuming there are 600k items in your DataQuery, this means that your list also contains 600k items.
However, you are not using that list at all so it's just chewing up all of your memory for no reason. Remove that and save yourself a whole tonne of memory and it should also run a lot faster.

how to insert a new notes document in the domino server with c# and the usage of interop.domino.dll?

This is my first question here.
I want to know the syntax to insert a new notes document in the lotus notes database if it is not existing using c#.
I have a code in vb script bit I do not know about vb script and lotus notes.
set doc = vw.GetDocumentByKey(empno)
if doc is nothing then
set doc = db.CreateDocument
doc.Form = "EmployeeRepository"
doc.Employno = empno
doc.FirstName = fname
doc.LastName = lname
doc.Group = grp
doc.Department = dept
doc.officeemailaddress = officemail
doc.officegeneralline = officegenline
doc.designation = desig
doc.officeaddress = officeadd
else
doc.FirstName = fname
doc.LastName = lname
doc.Group = grp
doc.Department = dept
doc.officeemailaddress = officemail
doc.officegeneralline = officegenline
doc.designation = desig
doc.officeaddress = officeadd
end if
call doc.save(true, true)
How can I achieve this in c#?
The C# syntax for the if statement is different. Instead of this:
if doc is nothing then
...
else
...
end if
You will need
if (doc != null)
{
...
}
else
{
...
}
Also, the C# language does not support shorthand notation doc.item = X. So the assignments in that format in the above code need to be changed to use the ReplaceItemValue method. I.e., instead of this:
doc.Form = "EmployeeRepository"
doc.Employno = empno
doc.FirstName = fname
doc.LastName = lname
you need to use this:
doc.ReplaceItemValue("Form","EmployeeRepository");
doc.ReplaceItemValue("Employno",empno);
doc.ReplaceItemValue("FirstName", fname);
doc.ReplaceItemValue("LastName", lname);
I might also suggest trying an ExpandoObject (although I haven't tried that yet, but I'm about to give it a go). It's a dynamic type so you have to be careful with how you create it, but you could keep adding additional properties to it without having to instantiate them directly:
dynamic noteDocument = new System.Dynamic.ExpandoObject();
noteDocument.ShortName = "wonkaWillie";
noteDocument.Comment = "No Comment";
noteDocument.MailSystem = "Other";
noteDocument.PowerLevel = "It's over NINE THOUSAND!!!!!";
I suppose you could just as easily (and probably be a little tighter of a solution) to have a pre-formatted class ready for the occasion of adding data into a specific document format too though.
So the ExpandoObject method works, but using a class with explicitly declared fields / properties is much cleaner....you can pass in an instance of a class to a method that performs this pretty handily:
class NotesDocumentItemClass
{
public string Form {get; set;} = "Person";
public string FullName {get; set;} = "Over 9000/Notes/Address/Or/Whatever";
}
and then pass an instance of that class into a method like.....
private bool AddEntry(NotesDatabase db, NoteDocumentItemClass d)
{
NotesDocument newDoc = db.CreateDocument();
doc.ReplaceItemValue("Form", d.Person);
doc.ReplaceItemValue("FullName", d.FullName);
return newDoc.Save();
}

Checkbox SelectedItem Text to Linq Database

I built an ASP.net usercontrol and I am trying to get the text from the checkbox to pass to the database. My problem is I keep getting an error on submission with the method I use. Here is what I used:
ResidenceHallInspection rhi = new ResidenceHallInspection();
rhi.versionId = version.id;
rhi.submitDate = DateTime.Now;
rhi.CheckInOrOut = ddlCheck.SelectedItem.Text;
rhi.StudentId = txtStudentId.Text;
rhi.FirstName = txtFirstName.Text;
rhi.MiddleName = txtMiddleName.Text;
rhi.LastName = txtLastName.Text;
rhi.Walls = chbxWalls.SelectedItem.Text;
rhi.Windows = chbxWindows.SelectedItem.Text;
rhi.Blinds = chbxBlinds.SelectedItem.Text;
rhi.Couch = chbxCouch.SelectedItem.Text;
rhi.CommonRoomCouch = chbxCRCouch.SelectedItem.Text;
rhi.CommonRoomChair = chbxCRChair.SelectedItem.Text;
rhi.Doors = chbxDoors.SelectedItem.Text;
rhi.Carpet = chbxCarpet.SelectedItem.Text;
rhi.Ceiling = chbxCeiling.SelectedItem.Text;
rhi.CommonRoomCounter = chbxCRCounter.SelectedItem.Text;
rhi.Cabinet = chbxCabinet.SelectedItem.Text;
rhi.Phone = chbxPhone.SelectedItem.Text;
rhi.Bed = chbxBed.SelectedItem.Text;
rhi.Desk = chbxDesk.SelectedItem.Text;
rhi.DeskChairs = chbxDeskChair.SelectedItem.Text;
rhi.Tub = chbxTub.SelectedItem.Text;
rhi.Vanity = chbxVanity.SelectedItem.Text;
rhi.Notes = txtNotes.Text;
rhi.Building = txtResHall.Text;
rhi.ApartmentNumber = txtSuitNo.Text;
rhi.BedSpace = txtBedSpace.Text;
house.AddToResidenceHallInspections(rhi);
house.SaveChanges()
It would be good to see more information, such as the error you received, and possible the code and/or HTML for the custom user control. However, there are a couple of possibilities which seem likely. One is that your SelectedItem property may be null, which would cause an ObjectReferenceException to occur. Another is that Text itself is null, and that your database doesn't allow a null value for one or more of the fields you're assigning.
You can get a better answer than this rather vague one if you provide more information.

Entity Framework 4 - Duplicate Key Upon Update

I'm having trouble performing an update in the Entity Framework. I don't really understand the behaviour I am seeing.
I am using the AdventureWorks database.
The starting value for the StateProvince is Micronesia. If I change it to Maryland, the update is successful. However, if I then try to change it back to Micronesia, I get the following error:
"Cannot insert duplicate key row in object 'Sales.SalesTerritory' with
unique index 'AK_SalesTerritory_Name'.\r\nThe statement has been
terminated."
The DAL method in question is:
public static void UpdateCustomer(CustomerDetails customerDetails)
{
AWEntities context = Common.GetContext();
var customerQuery = from c in context.Individuals
.Include("Contact")
.Include("Customer.CustomerAddresses.Address.StateProvince.SalesTerritory")
//.Include("Customer.SalesTerritory.StateProvinces")
.Where(id => id.CustomerID == customerDetails.CustomerId)
select c;
var individual = customerQuery.ToList().ElementAt(0);
Contact contact = individual.Contact;
contact.LastName = customerDetails.LastName;
contact.MiddleName = customerDetails.MiddleName;
contact.FirstName = customerDetails.FirstName;
contact.EmailAddress = customerDetails.EmailAddress;
contact.Phone = customerDetails.Phone;
contact.Title = customerDetails.Title;
AWModel.Customer customer = individual.Customer;
customer.CustomerID = customerDetails.CustomerId;
customer.SalesTerritory.Name = customerDetails.SalesTerritory;
Address address = individual.Customer.CustomerAddresses.ElementAt(0).Address;
address.AddressLine1 = customerDetails.AddressLine1;
address.AddressLine2 = customerDetails.AddressLine2;
address.City = customerDetails.City;
address.PostalCode = customerDetails.PostalCode;
address.StateProvinceID = customerDetails.SalesProvinceId;
context.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);
}
Can anyone identify the correct way to do what I am attempting.
This is occurring when you update the SalesTerritory.Name property:
customer.SalesTerritory.Name = customerDetails.SalesTerritory;
The effect is to change the SalesTerritory entity, rather than the customer entity. I believe you want something more like:
customer.SalesTerritoryID = customerDetails.SalesTerritoryID;

Categories

Resources