Database Question (LINQ-to-SQL) - asp.net

I am currently working on a website where we can track small event for our clients. I am using linq-to-sql and asp.net to build it. So far the site is really small about 10 pages, and only 2 tables, events and clients. I have listed the columns for each table below:
Events:
-eventid
-eventname
-datecreated
-details
-datedue
-status
-clientname (this should be clientid)
-sentemail
Clients:
-clientid
-clientname
-clientemail
-clientphone
the issue I am having is getting the 2 database tables* to work together. Ideally I would like to have clientname replaced with clientid in the Events table.
I had it set up this way before but ran into an issue when listing out the events:
When I am listing out the events I would like it to show the client name as appose to the clientID. Unfortunately I am pretty new to ASP.net and although I could easily do it in PHP have no idea how to get it to work. Its not a huge deal but I would like to be able to update the client list and events apart from one another.
Sorry If this makes little to no sense, If there is any confusion I will try to word it better.
*correction on my part

Once you've got your database normalized, create a Linq2Sql context, and then you can write a query similar to this (to get a list of event names and their client names):
var results = from e in dbContext.Events join c in dbContext.Clients on e.clientid equals c.clientid select new { e.eventname, c.clientname };

in addition to the answer of Andrew Lewis you need to:
1) add the clientid field to the events table
2) run a sql query to fill the clientid field:
update events set clientid = (select clientid from client where name = events.clientname)
3) remove the clientname field from the events table

Related

In App Maker, how do you make dynamic table cell text?

In App Maker, I am displaying a table and want to replace table cell data with different text using a data lookup from another table. Assume two tables, Departments and Employees.
Departments is two fields, DeptID and DeptDescription.
Employees is multiple fields including DeptID.
In the table listing for Employees, I would like to replace the DeptID with the DeptDescription. (The page datasource is Employees. I do not want to set up a relationship between the data models.)
I am guessing I want to do some scripting in the onDataLoad event for the table cell label for DeptID. I have this much so far:
app.datasources.Departments.query.filters.DeptID._equals = widget.datasource.item.DeptID;
app.datasources.Departments.newQuery().run();
widget.text = app.datasources.Departments.item.DeptDescription;
I know this is not correct, but am I close?
This answer is untested, but I wanted to present a possible solution that would not require a lot of DB calls, especially ones that make repeated calls to a server script which might consume a lot of processing time when you do line item calls.
Set up a separate datasource under the Department model. Change the default 'Query Builder' to 'Query Script' and add a parameter of type 'list(number)' or 'list(string)', this should match your Primary Key field type. Uncheck the 'auto load' option.
In your 'Query Script' portion enter the following code:
query.filters.Id._in = query.parameters.YourParameter;
return query.run();
Go to your Employees datasource that is supposed to generate your table and find your 'On Load' client script section. In this section enter the following code:
var departmentsDs = app.datasources.YourDepartmentsDs;
departmentsDs.properties.YourParameter = datasource.items.map(function(deptIds) {return deptIds.DeptID;});
departmentDs.load();
Now go the page that contains your table. If you have not already create a label widget do so now. In this label widget for the text binding enter the following:
#datasources.YourDepartmentsDs.loaded && (#datasources.YourDepartmentsDs.items).map(function(Id){return Id.Id}).indexOf(#widget.datasource.item.DeptID) !== -1 ? #datasources.YourDepartmentDs.items[(#datasources.YourDepartmentsDs.items).map(function(Id){return Id.Id}).indexOf(#widget.datasource.item.DeptID)].DeptDescription : 'Unable to retrieve Dept Description'
As stated this is untested and I wrote the code from memory without App Maker in front of me so it may require some additional tweaking. Going with the first option presented by J.G. would also be a very viable solution though. And I apologize but the code formatter does not seem to be working for me.
1 way) Create an aggregate table that joins your tables if you need to bypass using the relations feature. This way you can use sql to join the two tables in the datasource definition
2) if you don't want to make a new table. Change the text from a value binding to "more options"
=getDescription(#datasource.item.DeptId)
and then the code you wrote in a client side script
function getDescription(id){
google.script.run
.withSuccessHandler(function successHandler(result){ return result;})
.withFailureHandler( function failureHandler(e){ console.log(" Failed" +e);})
.queryValue(id);
}
server side script:
function queryValue(id){
var query = app.models.Departments.newQuery();
query.filters.DeptID._equals = id;
var results = query.run();
return results[0]["DeptDescription"];
}
that last line might be results[0].DeptDescription

asp.net multi-row update with gridview control without looping (vb.net)

I'm pretty new to asp.net. I'm building my first real app as a test. using SQL Server 2008 RS, VS Express 2012, IIS7.x and asp.net4.0
We receive Fedex shipment info every night that gets inserted into an MSSQL DB using SSIS. We then import the invoice, do variance matching and book costs to jobs based on the job no in Ref1 field. All this works great. However, the shipping department are supposed to put the ONLY the JobNo in the ref1 field. Of course they don't and there a lot of temps and shipping stations, so we need to fix the data. They'll put JobNo followed by junk, or junk and then the job no. When the costing people are looking at the invoice it's usually obvious what the job no is (e.g. "Samples for job 123" should be "123"). There can be many rows with the same Ref1 that needs editing (e.g 20 cartons with same Ref1). I have an SP with 3 params (OldRef, NewRef, invNo) that updates the Ref no for all records on that invoices:
UPDATE InvoiceLines
SET REF1 = #NewRef1
WHERE InvNo = #InvNo and Ref1 = #OldRef1
I figured a GridView (with an sqldatasource) would be a nice way to present the data. I only show rows where the Ref1 field is invalid, as the user corrects them, the no of records reduces.
I want the user to select a row, edit the Ref1 value and I'd just get the (old) RefNo of the selected row, it's new value, and call my SP with those and the InvNo (from a DropDown that filtered the invoice lines table).
Turns out to be way more difficult/inefficient that I thought.
All the examples I found to do this type of thing, make the user click all the rows and them loop through every row to do an update. Talk about slow and painful. I want to execute a single SP and have all matching rows updated and then refresh the list.
So what I'd like to figure out is how to get the OLD Ref1 (value in Ref1 before the edit - like deleted in an SQL trigger), the NEW Ref1 (edited value that the user typed in Ref1 - like inserted in an SQL trigger) and execute my SP and then refresh the table with the updated value result set.
Am I better off with something other than a grid view, or just using something other than the built in Edit command?
If I do figure out how to do the update, how do I refresh the GridView.
Can anyone point me in the right direction?
On another note, I'm on the fence about switching to C#. Most of the examples I'm finding are in C#. I learned C++ many years ago and read up on C# at weekend. It doesn't seem too difficult. I did find a Microsoft white paper and it pretty much said there's little difference between VB and C# so no real reason to switch. My colleagues do not know C or C#, so I'm just a bit concerned that in the unlikely event they need to help out, they'll be stuck. Any thoughts on this?
Regards
Mark

Qt: QSqlTableModel + QTableView sync with PostgreSQL

I'm writing a database access app for storing some data and want to ask a few questions about the model/view architecture.
(Using: Qt 4.7.4, own build; PostgreSQL 9.0; Targets: WinXP, Win7 (32/64 bit))
Let me first explain what I am trying to achieve and where I am currently.
I have two pages (subclassed QWidgets inserted in a QStackedWidget) with a QTableView bound to a model. Each view is bound to a table in the PostgreSQL server. You can add/edit/delete/sort/filter items.
Each page can be seen by only one type of users, lets call the roles Role1 and Role2.
The submit strategies of everything connected to the model are OnManualSubmit.
(Transaction isolation level = Serializable.) When two users want to edit(for example) the same row, I want to do a "SELECT ... FOR UPDATE" query - to make sure that when someone edits something, he will merge his changes with newer ones (if any, just like in SVN for example). But I see only a submitAll() method the QSqlTableModel.
Maybe catching the signals beforeUpdate(), beforeDelete(), beforeInsert() and performing manually "SELECT ... FOR UPDATE" is one option.
The other way I think is to subclass QSqlTableModel. What is the clean and nice way to achieve this?
I want to periodically update the QSqlTableView for each of the pages (one page is seen at most, Role1 users have access only to Page1 and the same for Role2 => Page2).
The first thing that came to my mind is to use a QTimer and manually call select() of the QSqlTableModel, but... not sure if this is the cool way.
I also want to periodically check if the connection to the database is ok, but I think that a QTimer + QSqlDatabase::isOpen () will do.
Now, the 2 tables have the same primary keys and some columns are the same. I want when a user with Role1 changes a row in Table1 to automatically change corresponding columns of Table2 and vice versa. Should I create a trigger in Postgres?
BTW, the database is small - each of the two tables is around 3-4000 rows with ~10 columns (varchars mostly, 1 text and 2 date colunms).
Thanks for reading and Happy New Year! :)
I think you should consider doing something of the following:
Instead of using QSqlTableModel as a model I'd implement my own model as a subclass of QAbstractTableModel. This will allow you a lot of control over what you can do in terms of data manipulation.
One thing that this will require is for certain fields in the table you would need to implement subclass of QAbstractItemDelegate that will allow for modification of data in the table as I am fairly sure you don't want to allow users updating any field in the table as for example primary key is likely have to be left alone.
For question 2 I would suggest implementing a field called transaction_counter for every row so you don't have to select every row in the table just the updated ones the transaction_counter will be updated on every row update and the new one will be inserted on the new row insert. One thing that will be required is that the counter is unique across the table. For example if initial state of the table is: row1 has counter = 0 and row2 has counter = 0. If row1 is updated counter set to 1. When row1 is then updated again counter on it is set to 2. When row2 is now updated counter on it is set to 3, etc. You can certainly do the data refreshes now using QTimer and this will be much more advantageous to for example checking the data as one user may be updating the same table as another user with the same Role.
For Question 3. I don't see any reason why not custom models and especially if you decide to separate data from the model you can manipulate data separately from it's display. Sort of Data->Model->View->Controller implementation. Each one can be maintained separately as long as you have a feedback mechanism for your delegates.
For Question 4. The answer is sure or you can implement the trigger in your application.
Hope this helps. Have a great New Year!

ASP: Data binding with controls

I am implementing an online parking reservation system and I need to bind a table with 2 Controls.
for example the user selects a Reservation start date and the parking location from a RadioButtonList and then a button (Search Availability) is pushed to fetch the parking from the database according to the Date selected and Location.
the question is: How can I bind the (Reservation Start Date Control) with (RadioButtonList) to both search in the database? and what would be the Sql Query?
Regards.
This is pretty basic stuff so you've got a lot of work ahead of you.
On your aspx page, you will want to use a SqlDataSource and add two ControlParameters to the SelectParameters, one for the RadioButtonList, one for the TextBox/Calendar with the date. Then create a GridView control to display the results and set the DataSource of the gridview to be the SqlDataSource.
Depending on your database schema, the SQL Statement will look something like this:
SELECT * FROM [Parking] WHERE [LotID] = #LotID AND [Date] = #Date AND [Reserved] = FALSE;
However, I have done reservation systems in the past, and queries to find available spots for a particular day are rarely simple. I would suggest worrying about writing the SQL query first and then getting the web page to run the query later. If you post information about your table schema and tag it as a SQL question you'll probably have better luck.
Hope this helps.

Entity Framework throws SqlDate exception on the *lookup* table

I am using Entity Framework with asp.net mvc, but I don't think mvc plays a big role here.
I have an object Customer, and a lookup table (there are several, and they all behave the same way; so for simplicity I'll pick Territory). Both Customer and Territory have LastUpdated field (Datetime that is set manually in the code).
If I hardcode Territory, and get only Customer data from the View, I don't have any problems:
public ActionResult CreateCustomer([Bind(Exclude = "CustId")] Customer cm) {
cm.Territory = (from t in repo.Territory where t.ID == 2 select t).First();
repo.AddToCustomer(cm);
repo.SaveChanges();
}
As I said, no problems. However, if I use a dropdown in the view with the matching id (Territory.ID) - there is a problem. I have the following line in controller:
ViewData["territory"] = new SelectList(repo.Territory, "ID", "Name", 1);
and corresponding line in the View:
Territory: <%= Html.DropDownList("Territory.ID", (IEnumerable<SelectListItem>)ViewData["territory"])%>
I get good news and bad news: the good news is that I get the territory ID nicely assigned to the appropriate member of Customer object. The bad news is that Territory.LastUpdated value is set to 1/01/0001. Obviously, I don't care about this value - but it looks like EF cares. When I call SaveChanges I am getting the following error:
SqlDateTime overflow. Must be between 1/1/1753 12:00:00 AM and 12/31/9999 11:59:59 PM
Looks like EF is trying to retrieve the value from the database, and then compare it with EF value... or maybe something else - but the bottom line is I can't figure out how to prevent it from trying to be so smart.
For now, I name DropDown ID to be something different ("terID" instead of "Territory.ID"), and using FormCollection:
int terID = Int32.Parse(formData["terID"]);
cm.Territory = (from d in repo.Territory
where d.ID == terID select d).First();
This works (which makes me comfortable with my analysis) but this cannot be the best way.
I also can't believe that nobody bumped into such problem - but I couldn't find anything relevant... The best I could find is link text but it's more of a hint without much details
I tried to cut out all unrelated stuff from the code - so if there are some typos, they are in the post; not necessarily in the code itself!
Thanks
Territory.LastUpdated is being set to the default value, as EF saves the whole row / what has changed you get an exception.
The easy way to fix this is to set it to DateTime.Now before saving.
I'm assuming you are using EF 1.0 which is not good at direct foreign key maping.
Territory posted from view to action is not bound to Datacontext, hence when you save your customer object - EF saves attached Territory Object as well.
You have to get Territory object from db first and then assign it to customer.
And Your solution is perfectly fine, cos there is no other for EF 1.0 )-:

Resources