I have asp.net grid view with default update and select columns (they are not converted to template columns)
Now I want to record whenever a user updates a row (i have a column in table: userlog which
can be displayed in the grid view but it is readonly)
I have tried to write my own update statement in GridView_RowUpdated event
but I am not getting the thing done, I wanted to append logged in user id, with
date post stamp, at the end of existing value in userlog column
Please help, currently I am doing the following, in RowUpdated event:
string sqlEL = "Select userlog from Schedule Where rowid=" + e.Keys[0].ToString();
string tmp = dao.GetSingle(sqlEL);
if (tmp == null || tmp == String.Empty)
tmp = ".";
string sqlUp = "Update Schedule set userlog='" + tmp + "' + '"
+ LogthisUser() + "' Where rowid=" + e.Keys[0].ToString();
dao.UpdateDB(sqlUp);
it was due to the fact that readonly column was a simple bound field
and in Asp.Net if you want to limit a column value in edit mode, still showing it
to the user in normal view, then it has to be template field, with EditItemTemplate
being removed
Related
I have a View with a data source of the shipment table. This view has a method that contains a query. This query takes a shipment id and returns the sales id from the sales line table for this shipment. This view has a computed field that is the output of the query. The computed field is then used on a form.
If I hard code the shipment id the process works correctly. My question is how do I get the shipment id dynamically from a list of shipment ids. For instance, I have a form that lists all shipments. I want to place a field next to the shipment id that contains the calculated sales id from the process above.
Bottom line: I want the first column of a grid to be a shipment id and the second column to be the sales id for the shipment in the first column.
This is an example of the method described above that contains the query:
private static server str findSalesLine()
{
WMSShipment wmsShipment;
WMSOrderTrans wmsOrderTrans;
SalesLine salesLine;
select wmsShipment
join wmsOrderTrans
where wmsShipment.shipmentId == '1040383'
&& wmsShipment.shipmentId == wmsOrderTrans.shipmentId
join salesId from salesLine
where salesLine.LineNum == wmsOrderTrans.inventTransRefLineNum
&& salesLine.SalesID == wmsOrderTrans.inventTransRefID
&& salesLine.ExternalItemId != '';
return salesLine.SalesId;
}
I would use a computed column similar to the below. I'm in a different environment than you so the SQL is not valid on my box but it should work on yours.
Add a new string computed column to your view, then set this method as the datamethod.
public static server str getSalesId()
{
tableName viewName = tableStr(testView);//name of your view
DataSourceName wmsShipmentDsName = identifierStr(WMSShipment);//change if your dsname is different on your view
str returnStr;
returnStr =
" SELECT G1.SALESID FROM SALESLINE G1 " + //don't use "T1 T2" etc as aliases on computed columns
" JOIN WMSORDERTRANS G2 ON " +
" G1.LINENUM = G2.INVENTTRANSREFLINENUM AND " +
" G1.SALESID = G2.INVENTTRANSREFID AND " +
" SALESLINE.EXTERNALITEMID <> '' " +
" WHERE G2.SHIPMENTID == " +
SysComputedColumn::returnField(viewName, wmsShipmentDsName, fieldStr(WMSShipment, ShipmentId));
return returnStr;
}
I think what you're looking for is a query range (https://msdn.microsoft.com/en-us/library/aa638454.aspx) or a display method (https://msdn.microsoft.com/en-us/library/aa595058.aspx)
Do you have any more detail or sample code?
I have a page where users select multiple search criteria to retrieve data from a SQL Server 2014 view. The view is grabbing data from a table on a linked server (I am not able to put the view directly on that server, and the table I am reading from has over 800 million rows so copying that data onto the local server isn't going to happen).
Of course, I can't index the view either (on linked server) so I'm trying to find a way to stop the timeouts from happening when the query is run. Is it possible to do something like this in a stored procedure?
SELECT
cast(trees as varchar(3)) as Trees
, MIN(fruitnumber) AS FN_Start
, MAX(fruitnumber) AS FN_End
, COUNT(CASE WHEN fruitType = 'apple' THEN 1 ELSE NULL END) AS apple
, COUNT(CASE WHEN fruitType = 'banana' THEN 1 ELSE NULL END) AS banana
FROM
view_fruitReport
WHERE
(orchard = #orchard) and
and here's where it gets wonky. Users select the orchard from a dropdown (not a combobox because we use IE11 and ajaxtoolkit combo box still doesn't work there) so only one selection possible but.
They are able to add criteria to listboxes. Unlimited criteria. And they don't need to select any of the criteria, they can just search by orchard.
So the rest of the WHERE clause is built based on what they have added to the listboxes.
Like this:
' check if items selected in both listboxes'
If trees_Listbox.Items.Count > 0 Then
If fruitminListBox.Items.Count > 0 Then
'cycle through items in fruitnum listbox to create an "in" clause for sql query'
For Each item As ListItem In trees_Listbox.Items
whereString += String.Join(",", item) + ", "
Next
whereString = Left(whereString, Len(whereString) - 2) + ")"
selectQry += "(" + wherecls + whereString + ")"
whereFNcls = "(fruitNumber between "
For Each itemFNmin As ListItem In fruitminListBox.Items
'create a "between" clause for the min and max FN values entered by user.'
whereOEcls += itemFNmin.Value + " and " + fruitmaxListBox.Items(i).ToString + ") or (fruitNumber between " '(fruitnumber between number and number) or '
i += 1
Next
'trim off the last text portion of the whereOEcls'
whereOEcls = Left(whereOEcls, Len(whereFNcls) - 25)
selectQry += " and (" + whereFNcls + ") GROUP BY trees ORDER BY trees"
fruityData.SelectCommand = selectQry
WeeklyGridView.Visible = True
Else
'see if FN is empty but trees is selected'
For Each item As ListItem In trees_Listbox.Items
whereString += String.Join(",", item) + ", "
Next
whereString = Left(whereString, Len(whereString) - 2)
selectQry += wherecls + whereString + ") GROUP BY trees ORDER BY trees"
fruityData.SelectCommand = selectQry
WeeklyGridView.Visible = True
End If
Else
Essentially ending up with a where clause that could look like this:
WHERE (orchard = #orchard)
and trees in (100,200,300,400)
and fruitnumber between (itemFNmin.Value and itemFNmax.Value)
or fruitnumber between (itemFNmin.Value and itemFNmax.Value)
etc etc etc
Which works except it makes things very ugly and I am certain is a poor way of doing this.
I have no clue if/how I can make these lists of variables pass to a stored procedure as multiple arrays or tables etc.
Probably anything is better than having them tied to a view, whose linked server table isn't even an indexed table (not my fault haha)
For your first question: You can return the Count of each fruit type, but it will have performance implications as it requires a subquery for each one. This also requires that you hard code each possible fruit type in the query. I assume that the fruit types can change or have other types added to them, so this isn't the most desirable in terms of maintenance either. You can't dynamically add columns to a query unless you build SQL in your proc and make use of sp_executesql, which is more convoluted than doing in line SQL in your .Net code.
SELECT
cast(trees as varchar(3)) as Trees
, MIN(fruitnumber) AS FN_Start
, MAX(fruitnumber) AS FN_End
, CASE
WHEN fruitType = 'apple' THEN (SELECT COUNT(fruitType) FROM view_fruitReport WHERE fruitType = 'apple') ELSE NULL
END AS [apple]
, CASE
WHEN fruitType = 'banana' THEN (SELECT COUNT(fruitType) FROM view_fruitReport WHERE fruitType = 'banana') ELSE NULL
END AS [banana]
FROM
view_fruitReport
WHERE
(orchard = #orchard)
For your second question, you can pass in lists/tables into a stored procedure. One method is to pass some sort of delimited string and parse it using T-SQL. I recommend a different approach, however, which is
Table Value Parameters. This is a parameter that acts as a table that you can join with in your stored procedure.
Here is an example for implementing a Table Value Parameter for the Trees column.
You will first need to declare a SQL Type:
CREATE TYPE [dbo].[Trees] AS TABLE (Trees INT)
Then you can reference it in your stored procedure as a parameter that acts as a table. Note that you can't use WITH(NOLOCK) with these and must specify READONLY in the paramter:
CREATE PROCEDURE [dbo].[up_getOrchardInfo]
(
#Trees As [dbo].[Trees] READONLY
, #Orchard INT
)
AS
BEGIN
SELECT
cast(trees as varchar(3)) as Trees
, MIN(fruitnumber) AS FN_Start
, MAX(fruitnumber) AS FN_End
, COUNT(CASE WHEN fruitType = 'apple' THEN 1 ELSE NULL END) AS apple
, COUNT(CASE WHEN fruitType = 'banana' THEN 1 ELSE NULL END) AS banana
FROM
view_fruitReport AS F
INNER JOIN #Trees AS T
ON F.Trees = T.Trees
WHERE
(orchard = #orchard)
END
GO
The above example will filter by the Trees passed in. Note that if want to return everything for the Orchard if #Trees is Null or the count is 0 you will need to include that conditional logic in your stored procedure.
IF (#Trees IS NULL OR (SELECT COUNT(1) FROM #Trees = 0))
BEGIN
--No Join to #Trees
END
ELSE
BEGIN
--Query from above.
END
Finally, on the .Net side you will need to pass in a DataTable object as a Parameter on the SqlCommand with the Type of Structured:
Dim sqlCommand As New SqlCommand("up_getOrchardInfo", sqlConnection.SqlConnection)
sqlCommand.CommandType = CommandType.StoredProcedure
Dim sqlTreesParameter As New SqlParameter("#Trees", SqlDbType.Structured)
sqlOrchardParameter.Direction = ParameterDirection.Input
Dim tblExample As New DataTable
tblExample.Columns.Add("Trees", New Integer().GetType())
Dim drExample As DataRow = tblExample.NewRow()
drExample.Item("Trees") = 100
tblExample.Rows.Add(drExample)
'Adjust if Orchard is a VarChar/String'
Dim sqlOrchardParameter As New SqlParameter("#Orchard", SqlDbType.Int)
sqlOrchardParameter.Direction = ParameterDirection.Input
sqlOrchardParameter.Value = intYourOrchardValue
sqlCommand.Parameters.Add(sqlTreesParameter)
sqlCommand.Parameters.Add(sqlOrchardParameter)
'Execute Dataset
All of this said, you may want to consider making multiple stored procedures. One stored procedure could be optimized for returning everything when only an Orchard is passed and another for when Trees are also passed. This depends on how many parameters you're dealing with.
Maybe there's a UX answer. When you know it's not going to come back for a long time give the user a heads up and confirm if they want to wait or not. (With check box on the confirmation that says, "don't show me this again.")
But don't re-event the godawful estimated file transfer time from Windows Explorer.
I am developing a spreadsheet uploader tool which creates/updates contacts, which will be added as a new option to my website.
The spreadsheet has the following columns:
Full Name
Job Title
Salutation
Qualifications
Company Name
Address Line 1
Address Line 2
Address Line 3
The database table structure is as below:
Contact(contact_id INT PK IDENTITY(1,1), fullname VARCHAR(30), jobtitle VARCHAR(100), salutation VARCHAR(100), qualifications VARCHAR(100), companyname VARCHAR(100) , address1 VARCHAR(100), address2 VARCHAR(100), address3 VARCHAR(100))
The rules are:
1. The Full name must contain at least one space (leading and/or trailing spaces will be trimmed).
2. Total length of the full name must not exceed 30 characters (including any space(s)).
3. 'Full Name' is the key field to identify an existing contact in the system. As such, raise a validation error if this field is
blank.
4. If a match is found on the 'Full Name', then the other fields of the contact will be updated with the values populated in the
spreadsheet.
5. If a match is not found on the key field, then create a new contact with the details.
6. When creating/updating a contact a value must be populated in at least one other column (in addition to the 'Full Name'), otherwise
raise a validation error.
The process:
There are two phases called 'Validation Phase' and 'Actual Upload' phase.
- When the spreadsheet is uploaded the spreadsheet has to be validated as per the rules above and display the validation/status messages (on screen):
For example:
Row 1 is the header row so it will not be validated.
Row 2: Error - Full Name cannot be empty
Row 3: OK - A contact will be created
Row 4: OK - Contact will be updated
Row 5: Error - Full Name must contain at least one space
Row 6: Error - At least one other column must be populated in addition to the 'Full Name'
The user will have two options here:
Cancel - Then the upload will not be proceeded any further (so the user will have a choice to correct the rows as per validation messages then re-upload it).
Continue - Then the upload will move to 'Actual Upload' phase and the contacts will either be created or updated (if there are no validation errors as per the rules above).
Also, the validation/status message (similar to the messages in validation phase) should be displayed on screen after the successful upload.
I have managed to work out everything I had illustrated above, but I had to re-validate each row in 'Actual Upload' phase (i.e. I'm doing the same checks twice).
My question is, is there a way to preserve the results from the validation phase so I don't have to re-validate each record in the second phase?
I'm develioping this using the NativeExcel libraries on .NET Framework (Version 4.0.30319.34209) using VB.NET/ASP.NET (and No VISUAL STUDIO).
Please note all the code will be written in the code-behind page using VB.NET (I have no choice here, sorry).
Any suggestions/help will be much appreciated.
Save the validation status messages as a List(Of String) and then make that a session variable so that you can use it as a prompt during the upload phase.
To read the Excel file:
right-click References>COM>Office xx.x Object Application
Microsoft.Office.Interop.Excel.Application exlApp = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook exlWb = exlApp.Workbooks.Open(#"C:\Users\user\Excelfile.xls");
Microsoft.Office.Interop.Excel.Worksheet exlWs = exlWb.Sheets["Sheet1"];
int col = Convert.ToInt32(usedRange.Columns.Count);
int row = Convert.ToInt32(usedRange.Rows.Count);
exlApp.Visible = true;
string[,] cellValue = new string[row + 1, col + 1];
for (int j = 1; j <= row - 1; j++)
{
for (int k = 1; k <= col - 1; k++)
{
cellValue[j, k] = exlWs.Cells[j, k + 1].ToString();
}
}
exlWb.Close();
exlWs = null;
exlWb = null;
exlApp.Quit();
exlApp = null;
I am facing following problem. I want a search field with a DropDowList next to it, where user can pick an item for which he wants to search. I have to make it with this LINQ code not just a SQL query.
Here's my code:
var Metadata = from m in db.Metadatas
join mm in db.Multimedias
on m.multimediaID equals mm.multimediaID
where (m. { Here would i have the selected value from the dropdownlist. } .ToString().Contains(textboxvalue) ||
mm. { Here would i have the selected value from the dropdownlist. } .ToString().Contains(textboxvalue))
&& mm.filetype.ToString().Contains(radiobuttonvalue)
I want to put something like: "Dropdownlist.selectedvalue" into the area { Here would i have the selected value from the dropdownlist. }
I hope you guys understand my idea and problem.
I am not sure why you are doing join on in your linq statement. That is not necessary if you Linq already knows about the relationship between the objects because there is a foreign key relationship setup in the database.
What you can do is this:
var Metedata = db.Metadatas;
switch(Dropdownlist.selectedvalue)
{
case "one":
Metadata = Metadata.Where(m => m.{selected value field}.Contains(textboxvalue));
break;
case "two":
Metadata = Metadata.Where(m => m.{selected value field}.Contains(textboxvalue));
break;
//More use cases
}
I am not sure what you will be selecting out of the list when you are done, but if it involves related objects (e.g. Multimedias) then you might want to look into DataLoadOptions (LinqToSQL) or .Include() (EntityFrameworks).
Just change your sql query:
if(supportgrp.SelectedItem.Text == "All")
sql ="SELECT * FROM QlyData where Date >='" + txtstartdate.Text + "' and Date<='" + txtenddate.Text + "'";
else
sql ="SELECT * FROM QlyData where Date >='" + txtstartdate.Text + "' and Date<='" + txtenddate.Text + "' and suppgrp = '" + supportgrp.Text + "'";
I have three editable date/time fields which the first two is (field1 and field2), style: Calendar/time control. Both of them are showing the time: hour and minutes, eg: 15:51.
The third field also (editable) which I want to show the difference between field1 and field2.
Eg: If field1 is 14:41 and field2 is 14:30, then field3 = 00:11. I've tried field1-field2 but isn't working. The form has automatic refresh fields property. Thanks!
Your third field needs to be computed, not editable.
If it HAS to be editable for some reason, and you want it to update when the other two fields are changed, do this:
Create a new field and make it computed-for-display and hidden. Give it a formula like this
#If(field1=null | field2=null; #Return(""); "");
seconds := field1-field2;
hours := #Integer(seconds/3600);
minutes := #Modulo(#Integer(seconds/60); 60);
output := #Right("00" + #Text(hours); 2) + ":" + #Right("00" + #Text(minutes); 2);
#setfield("field3"; output);
#Command([ViewRefreshFields]);
""
Phil
I wrote this code, much easier...
Fields 'StartTime' and 'EndTime':
Type Date/Time, use Calendar/Time control, set it to only display time.
Check the property "Run Exiting/OnChange events after value changes".
The Exiting event should look like this:
Sub Exiting(Source As Field)
Call UpdateDuration()
End Sub
Field 'Duration':
Editable text field, but hidden.
Field 'dspDuration':
Computed for display text field. Value is just "Duration" (no quotes).
Then add the following code to the forms Global section:
Sub UpdateDuration()
Dim ws As New NotesUIWorkspace
Dim uidoc As NotesUIDocument
Dim starttime As NotesDateTime
Dim endtime As NotesDateTime
Dim duration As Integer
Set uidoc = ws.CurrentDocument
'*** Exit if not both times are entered
If uidoc.FieldGetText("StartTime") = "" Then
Exit Sub
Elseif uidoc.FieldGetText("StartTime") = "" Then
Exit Sub
End If
'*** Calculate duration in seconds and update field
Set starttime = New NotesDateTime( uidoc.FieldGetText("StartTime") )
Set endtime = New NotesDateTime( uidoc.FieldGetText("EndTime") )
duration = endtime.TimeDifference( starttime )
Call uidoc.FieldSetText("Duration", Cstr(duration) )
Call uidoc.Refresh()
End Sub
That's it. Easy, isn't it? If you want to modify the output (duration), you can easily do that, perhaps change it into minutes by diving it by 60.
Make sure you are getting the difference between two date time fields. If you need to, you can use the #TextToTime formula to convert text to a datetime type.
Then just subtract the first date from the second date and you'll get the difference in seconds.
Then divide that by 60 to get the difference in minutes.