I use this code for get the new value for the product, but i want to see this one on the screen, i used:
”row.UnitPrice”, but the data is there, but no on the screen.
So i need to call some another funtion for update it?
protected void SOLine_InventoryID_FieldUpdated(PXCache cache, PXFieldUpdatedEventArgs e)
{
var row = (SOLine)e.Row;
row.UnitPrice = null;
if (row.OrderType == "SO")
{
if (row.InventoryID != null)
{
InventoryItem oItem = PXSelect<InventoryItem,Where<InventoryItem.inventoryID,Equal<Required<InventoryItem.inventoryID>>>>.Select(new PXGraph(), row.InventoryID);
if (oItem != null)
{
decimal? qty = row.Qty;
row.UnitPrice = CalcLinePrice( oItem.RecPrice,qty);
Base.Transactions.Update(row);
}
}
}
}
protected decimal? CalcLinePrice(decimal? unitPrice, decimal? qty)
{
return unitPrice *2 * (qty);
}
Agree with Hybridzz: you should update CuryUnitPrice field instead of UnitPrice. Also it's necessary to use PXCache.SetValueExt method to raise all field-level handlers for the CuryUnitPrice field when assigning new value:
sender.SetValueExt<SOLine.curyUnitPrice>(e.Row, price);
On a side note:
you should never invoke Update method for currently processed record in FieldUpdated handlers - Base.Transactions.Update(row); must go away
static PXSelectorAttribute.Select method must be used to retrieve InventoryItem selected for SOLine record:
the PXSelectorAttribute stores records in single GlobalCache storage shared among all user sessions: it's a more efficient option in comparison to QueryCache of the PXView class accessible only for 1 user
reduce maintenance costs as you don't need to update BQL queries in multiple places if someone change BQL query for the SOLine.InventoryItem field
The 'Unit Price' column in the Details grid is associated with the field CuryUnitPrice and not the UnitPrice.
So you might need to update the correct DAC field.
row.CuryUnitPrice = CalcLinePrice( oItem.RecPrice,qty);
Related
I have a data in mysql and I want to display the data one by one everytime I click the button. How to do it?
string ConnectToServer = #"server=..*.;port=****; user id=sampleID; password=samplePW; database=sampleDB; pooling=false";
public void GetNames()
{
MySqlConnection NameConnector = null;
MySqlDataReader NameReader = null;
try
{
NameConnector = new MySqlConnection(ConnectToServer);
NameConnector.Open();
string Name = "SELECT * from sampleNames";
MySqlCommand NameCommand = new MySqlCommand(Name, NameConnector);
NameReader = NameCommand.ExecuteReader();
while (NameReader.Read())
{
Console.WriteLine(NameReader.GetInt32(0) + ": " + NameReader.GetString(1));
NameLabel.Text += NameReader.GetString("Names") + "\n";
}
}
catch (MySqlException NameException)
{
Console.WriteLine("error : (0)", NameException.ToString());
}
finally
{
if (NameReader != null)
{
NameReader.Close();
}
if (NameConnector != null)
{
NameConnector.Close();
}
}
}
private void ButtonName_Click(object sender, EventArgs e)
{
GetNames();
}
the output:
Name1
Name2
Name3
Name4
Name5
but I wan't is, the Name will appear one by one each time I click the button
like this:
click = output Name1
click = output Name2
click = output Name3
click = output Name4
click = output Name5
There are at least 2 ways of doing that depending on how real-time you need the data and how many DB calls do you want to make. here they are:
Option #1
Initialize a class level variable for names list and an index variable.
List<string> names = null;
int currentNameIndex = 0;
on the click handler, if names is null, populate the names variable with all names in the DB. display the first item as follows.
private void ButtonName_Click(object sender, EventArgs e)
{
if (names == null)
{
names = GetNames();
}
if (currentNameIndex < names.Count)
{
NameLabel.Text += names[currentNameIndex++];
}
}
the getnames need to be modified to return the list of names.
Option #2
Instead of retrieving the whole list in 1 DB call, you could change the SQL query to get the first record from the Table. (based on a Id or some key)
On a click, GetNames will retrieve only 1 record and display that.
On the next click it'll retrieve another record, but not the first ones.
This would typically involve a query involving a key column. Please post your table schema and I can answer with the Query.
an e.g. Query is
int currentNameId = -1; // class level variable.
query is
Select TOP 1 nameId, names from SampleNames Where NameId > currentNameId Order By NameId;
currentNameId = int.Parse(NameReader[nameId].ToString());
the above query assumes that nameId is a unique key and that values start from 0 or greater than -1, and that they are incremental. (identity PKs etc.)
as I mentioned, if you can provide the table structure, we can answer better.
Option #1 is efficient in DB calls but may potentially have stale data.
Option #2 is more chatty but has more real-time data than Option #1.
You are reading all records:
while (NameReader.Read())
If you want to read just one, try put all your connection outside the method and run
NameReader = NameCommand.ExecuteReader();
only once.
Then change
while (NameReader.Read())
to
NameReader.Read()
I am looking to find the best way to cache the DB Lookup Tables which consists of about 75 table.
I want to cache these tables data to use them in my application so I won't open a connection with the DB each time I need them.
Here is what I am doing:
I have created a static class which contains static properties to each lookup table called MyApplicationCache.
In each property getter I am filling it with the intended data from DB.
I'm caching the data using HttpRuntime.Cache["PropertyName"]
Each time i GET this lookup table data I check if the HttpRuntime.Cache["PropertyName"] != null
If yes then I am getting it from cache else I am getting it from DB
Finally, I am invoking all properties at application start event in global.asax
Until now everything is good, but recently I've faced a performance issue and I can't solve it. If I wanted the cache object (Payer) to be updated from DB I am doing this:
MyApplicationCache.Payer = null;
This sets HttpRuntime.Cache["Payer"] = null so if I requested it again it reloads it from the DB.
list<payer> payerList = MyApplicationCache.Payer;
Now the Performance problem raises:
PayerList in DB are about 1700 record.
Each payer object has a List property called PayerBranches which requires looping on all PayerList List and getting PayerBranches for each PayerList item.
// MyApplicationCache Payer Property:
public static List<LDM.DataEntityTier.Payer> Payer {
get {
if (HttpRuntime.Cache["Payer"] != null)
return (List<LDM.DataEntityTier.Payer>)HttpRuntime.Cache["Payer"];
// request item from its original source
using (LDM.DataAccess.OracleManager OracleManager = new LDM.DataAccess.OracleManager()) {
OracleManager.OpenConnection();
List<LDM.DataEntityTier.Payer> result = new LDM.DataService.PayerService().GetPayersListWithFullName(3, OracleManager, "UTC");
//List<LDM.DataEntityTier.Payer> result = new LDM.DataService.PayerService().GetListOfPayer("Order by Name asc", OracleManager ,"UTC");
List<PayerBranches> payerBranchesList = new LDM.DataService.PayerBranchesService().GetListOfObject(OracleManager, "UTC");
OracleManager.CloseConnection();
foreach (Payer payerItem in result) {
payerItem.PayerBranches = new List<PayerBranches>();
foreach (PayerBranches item in payerBranchesList.FindAll(x => x.PayerID == payerItem.Id)) {
payerItem.PayerBranches.Add(item);
}
}
// add item to cache
HttpRuntime.Cache["Payer"] = result;
return result;
}
}
set {
if (value == null) {
HttpRuntime.Cache.Remove("Payer");
}
}
}
This problem occurs with each property that has a list in it
I don't know if there is a better way to cache data or if there is a problem in my code.
Is there is a better way to do caching?
In this method, I am inserting a new item (Room) into the database. That process functions as expected.
But, in addition to that, each time I add a room, I want to add a piece of furniture as the initial piece. Each item of type Furniture has a "RoomID" to designate its location. Thus, Room contains a collection of Furniture. Below, I am the piece of "primary" furniture from the database, adding it to the room's furniture collection, and submitting changes. The room gets added to the database, but the Furniture.RoomID column remains as null.
public void AddResidentToUniverse(int residentID, int universeID)
{
Universe uni = _context.Universes.FirstOrDefault(u => u.UniverseID == universeID);
Resident res = _context.Residents.FirstOrDefault(r=>r.ResidentID == residentID);
if (uni != null && res!=null)
{
Room e = new Room();
Furniture primary = _context.Furnitures.FirstOrDefault(p => p.FurnitureID == new FurnitureController().GetPrimary(universeID).FurnitureID);
e.UniverseID = uni.UniverseID;
e.RoomName = res.RootName;
e.ResidentID = residentID;
e.Expired = null;
e.Furniture.Add(primary);
uni.Rooms.Add(e);
_context.SubmitChanges();
}
}
You need to add a line that tells your database what you want to insert. For example,
uni.Rooms.InsertOnSubmit(Room object);
uni.Furniture.InsertOnSubmit(furniture piece);
after this, you can write your
uni.SubmitChanges();
line.
I finally bit the bullet and erase my dbml, dropped and recreated the tables, and recreated my dbml. The Furniture.RoomID column updates correctly now. A totally unsatisfying, ham-handed and brute-force approach, I know.
Am new to this guys need your help! Am trying to multiply two field and the answer to that will be the result of my computed field. One field is from another table..
partial void SubTotal_Compute(ref decimal result)
{
// Set result to the desired field value
result = this.Quantity * this.Rate.PulaPerUnit;
}
Every-time i try to add a new record to the table i get a Null Reference exception
Rate is likely to be null. You should add a test for it before performing your calculation, e.g.
if (Rate != null)
{
result = Quantity * Rate.PulaPerUnit;
}
You should probably ensure that Rate has been set before you call Subtotal_Compute.
Initially I had a method in our DL that would take in the object it's updating like so:
internal void UpdateCash(Cash Cash)
{
using (OurCustomDbConnection conn = CreateConnection("UpdateCash"))
{
conn.CommandText = #"update Cash
set captureID = #captureID,
ac_code = #acCode,
captureDate = #captureDate,
errmsg = #errorMessage,
isDebit = #isDebit,
SourceInfoID = #sourceInfoID,
PayPalTransactionInfoID = #payPalTransactionInfoID,
CreditCardTransactionInfoID = #CreditCardTransactionInfoID
where id = #cashID";
conn.AddParam("#captureID", cash.CaptureID);
conn.AddParam("#acCode", cash.ActionCode);
conn.AddParam("#captureDate", cash.CaptureDate);
conn.AddParam("#errorMessage", cash.ErrorMessage);
conn.AddParam("#isDebit", cyberCash.IsDebit);
conn.AddParam("#PayPalTransactionInfoID", cash.PayPalTransactionInfoID);
conn.AddParam("#CreditCardTransactionInfoID", cash.CreditCardTransactionInfoID);
conn.AddParam("#sourceInfoID", cash.SourceInfoID);
conn.AddParam("#cashID", cash.Id);
conn.ExecuteNonQuery();
}
}
My boss felt that creating an object every time just to update one or two fields is overkill. But I had a couple places in code using this. He recommended using just UpdateCash and sending in the ID for CAsh and field I want to update. Well the problem is I have 2 places in code using my original method. And those 2 places are updating 2 completely different fields in the Cash table. Before I was just able to get the existing Cash record and shove it into a Cash object, then update the properties I wanted to be updated in the DB, then send back the cash object to my method above.
I need some advice on what to do here. I have 2 methods and they have the same signature. I'm not quite sure what to rename these because both are updating 2 completely different fields in the Cash table:
internal void UpdateCash(int cashID, int paypalCaptureID)
{
using (OurCustomDbConnection conn = CreateConnection("UpdateCash"))
{
conn.CommandText = #"update Cash
set CaptureID = #paypalCaptureID
where id = #cashID";
conn.AddParam("#captureID", paypalCaptureID);
conn.ExecuteNonQuery();
}
}
internal void UpdateCash(int cashID, int PayPalTransactionInfoID)
{
using (OurCustomDbConnection conn = CreateConnection("UpdateCash"))
{
conn.CommandText = #"update Cash
set PaymentSourceID = #PayPalTransactionInfoID
where id = #cashID";
conn.AddParam("#PayPalTransactionInfoID", PayPalTransactionInfoID);
conn.ExecuteNonQuery();
}
}
So I thought hmm, maybe change the names to these so that they are now unique and somewhat explain what field its updating:
UpdateCashOrderID
UpdateCashTransactionInfoID
ok but that's not really very good names. And I can't go too generic, for example:
UpdateCashTransaction(int cashID, paypalTransactionID)
What if we have different types of transactionIDs that the cash record holds besides just the paypalTransactionInfoID? such as the creditCardInfoID? Then what? Transaction doesn't tell me what kind. And furthermore what if you're updating 2 fields so you have 2 params next to the cashID param:
UpdateCashTransaction(int cashID, paypalTransactionID, someOtherFieldIWantToUpdate)
see my frustration? what's the best way to handle this is my boss doesn't like my first route?
Why not just:
UpdateCashPaymentSource(int cashID, int PayPalTransactionInfoID)
UpdateCashCapture(int cashID, int paypalCaptureID)
My boss felt that creating an object every time just to update one or two fields is overkill.
He would be right, if you have to create the object every time. The correct response to this is that you should already be using these business objects throughout your app. You don't create a new Cash object. You pass it the Cash object you already have to be saved.
"UpdateCashWithCapture" and "UpdateCashWithTransaction"?
UpdateCashByTransactionInfoID
UpdateCashByCaptureID()
?
Would one method and an enum cut it?
internal void UpdateCash(int cashID, int id, FieldName field)
{
using (OurCustomDbConnection conn = CreateConnection("UpdateCash"))
{
conn.CommandText = string.format("update Cash set {0} = #id where id = #cashID", field.ToString());
conn.AddParam("#id", id);
conn.AddParam("#cashId", cashId);
conn.ExecuteNonQuery();
}
}
public enum FieldName
{
PayPalCaptureId,
PayPalTransactionInfoID
}
EDIT:
On now reading your edit, I would agree that your original approach would be the way to go, in my opinion - passing in an object and updating all of the associated fields in a database compared to passing in an object property value and updating that in a database, the biggest performance killer will be opening the database connection, not the number of fields relating to one database record.
How about UpdateCashByCaptureID and UpdateCashByTransactionInfoID?
Add the name of the field being updated, i.e.
internal void UpdateCash_paypalCaptureID(...)
internal void UpdateCash_PayPalTransactionInfoID(...)
You could encapsulate the update query logic in a class:
public abstract class CashUpdateQuery
{
public CashUpdateQuery(int cashId)
{
this.CashId = cashId;
}
protected int CashId { get; private set; }
public abstract void SetConnectionProperties(OurCustomDbConnection conn);
}
Then you can have specific subclasses for each update scenario. So for your PayPal query you'd have something like this:
public PaypalTransactionCashUpdateQuery : CashUpdateQuery
{
private readonly int paypalCaptureId;
public PaypalTransationCashUpdateQuery(int cashId, int paypalCaptureId)
{
this.paypalCaptureId = paypalCaptureId;
}
public override void SetConnectionProperties(OurCustomDbConnection conn)
{
conn.CommandText = #"update Cash
set CaptureID = #paypalCaptureID
where id = #cashID";
conn.AddParam("#captureID", this.paypalCaptureId);
conn.AddParam("#cashID", this.CashId);
}
}
Then your update method can take a query object and use it to set the query properties on the connection and execute it:
internal void UpdateCash(CashUpdateQuery query)
{
using(OurCustomDbConnection conn = CreateConnection("UpdateCash"))
{
query.SetConnectionProperties(conn);
conn.ExecuteNonQuery();
}
}
This means that adding new queries is simply a case of adding a new subclass of CashUpdateQuery.