ASP.NET and a One-to-Many-to-Many Scenario - asp.net

I'm new to ASP.NET but not to programming. I am migrating our current site from PHP/MySQL to ASP.NET(3.5)/SqlServer. I've been lurking here since the site's launch, so I'm confident that one (or more) of you can help me out. Here's the scenario:
This is a training department site and the dept. has a course catalog stored in the table course. Each course may have many prerequisite courses, For example, A and B are prerequisites for C. I would normally store this either as a comma-delimited column in course or in a separate table course_prereq or course_course as a recursive relationship. This part I can do.
However, the business rules require that each course can have multiple sets of prerequisites. Fore example, N requires A, B and C, or N requires X and Y. This is where I'm stuck.
Previously, I stored this information in a column for row N as A,B,C|X,Y, parsed the ids into a PHP 2D-array, submitted a second query for all the rows whose id was in that array, then used PHP to separate those rows into their respective groups. Once all this processing is done, the groups of prerequisites are displayed as separate tables on the web page, like so:
| A | A's information goes here |
| B | B's information goes here |
| C | C's information goes here |
- - - - - - - OR - - - - - - - -
| X | X's information goes here |
| Y | Y's information goes here |
How would I accomplish this using ASP.NET?

Add a table to hold Prerequisite Sets. This table holds a set ID and key back to the courses table for each course in the set. The table may have several rows for a given set ID, so your primary key will be the set ID plus the course ID. Then in your course_prereq table you relate courses to the different prerequisite sets. An OR relationship can be assumed there because any ANDs are enforced in the sets themsevles.

Have a table called PrerequisiteSet that FKs to each prereq. Then have a Course_PrerequisiteSet many to many table that FKs to Course and PrerequisiteSet. Most of the time there will only be one entry in Course_PrerequistieSet, but if there are more than one, then it will be an OR relationship.

Both the answers above were very helpful. I ended up using just one database table instead of the suggested two. The table contains a course_id, prereq_id, and set_id, which all together form the primary key.
In the ASP.NET page, I use a repeater to loop over the sqldatasource stored procedure that returns a course's prerequisite sets, and a gridview inside that repeater that reads the individual prerequisite information from a second sqldatasource stored procedure. Like this:
RepeaterSqlDataSource (returns set ids)
Repeater
. . . GridViewSqlDataSource (returns course info for each prereq_id in set
. . . GridView
Hope this is helpful to anyone else looking at a similar scenario.

Related

Oracle APEX Search Engine

I'm using Oracle APEX 4.2.6 and Oracle DB 11gR2
I've an interactive report showing the list of clients.
The end user can modify the Name of the client.
My issue is that I have to find a way to allow the end user to find the modified client by seraching it with his old name.
For example, the end user modify the name of client from OLD NAME to NEW NAME
In the serach engine of the interactive report, the end users must be able to find the client by serching it by its old name OLD NAME
Is there a way to manage this situation on the APEX side or Database side.
This is very much a database issue, not an APEX issue. When the user modifies the client name, you will need to record the old name somewhere: this could simply be an OLD_NAME column on the CLIENTS table (which would only support knowing the previous name for a single name change), or it could be a CLIENT_NAME_HISTORY table to which a row is added every time a client name is changed.
Having done that, your interactive report's SQL can then be modified to search both old and new names to find the client - for example:
select ...
from clients
where (name like :P1_NAME or old_name like :P1_NAME)
or
select ...
from clients c
where (c.name like :P1_NAME or exists (select null
from client_name_history h
where h.client_id = c.client_id
and h.name like :P1_NAME)
Note that I think you will need to create a page item for the name filter, because the built-in filter of the IR can only search data that is displayed in the report, which previous names will not be (presumably).
Having additional columns might not be a "scalable" solution. What if another user changes the name again? And again? And again?
A better approach to store this data would be in rows that are uniquely identified by a combination of the primary key of the client along with an object version identifier - this could be a number or a time stamp or a date range. This is an approach that Oracle themselves use in many of its enterprise application.
Example of the data would look like below.
1.) Using Object Version Number
Client Id | Client Name | Object Version Number
1 | Bob | 1
1 | Sam | 2
1 | Ed | 3
Here, every time a user changes the name an additional row is created maintaining the same client_id value but incrementing the object version number by 1. The highest ovn represents the latest value. You could also have a column called "latest_record" and insert a value of Y when creating a new record to show that this is the latest record (resetting the value in the previous latest record to N). Similarly, instead of a number, you can simply store the timestamp and use that to determine the latest record.
Using date range
Client Id | Client Name | Start Date | End Date
1 | Bob | 01-Jan-2017 | 31-Jan-2017
1 | Sam | 02-Feb-2017 | 02-Mar-2017
1 | Ed | 03-Mar-2017 |
In this approach, you are specifying the period of time for which the name was valid. A use case would be an individual taking the adopting the surname of their partner after marriage. In such a case, one name was valid from the time of birth to the date of marriage and another name was valid from the date of marriage onwards.
Once you prepare your datastructure in this format, in the apex report you just need to query on the single name column. I feel additional tables and columns are an unnecessary overhead in this case.
Regards,
SJ

How to create a PL/SQL package to discard multiple level of cascading views

I am working on a CR where I need to create a PL/SQL package and I am bit confused about the approach.
Background : There is a View named ‘D’ which is at end of the chain of interdependent views in sequence.
We can put it as :
A – Fact table (Populated using Informatica, source MS-Dynamics)
B – View 1 based on fact table
C – View 2 based on View1
D – View 3 based on view2
Each view has multiple joins with other tables in structure along with the base view.
Requirement: Client wants to remove all these views and create a PL/SQL Package which can insert data directly from MS-Dynamics to View3 i.e., ‘D’.
Before I come up with something complex. I would like to know, is there any standard approach to address such requirements.
Any advice/suggestions are appreciated.
It should be obvious that you still need a fact table to keep some data.
You could get rid of B and C by making D more complex (the WITH clause might help to keep it overseeable).
Inserting data into D is (most likely) not possible per se, but you can create and INSTEAD OF INSERT trigger to handle that, i.e. insert into the fact table A instead.
Example for using the WITH clause:
Instead of
create view b as select * from dual;
create view c as select * from b;
create view d as select * from c;
you could write
create view d as
with b as (select * from dual),
c as (select * from b)
select * from c;
As you can see, the existing view definition goes 1:1 into the WITH clause, so it's not too difficult to create a view to combine all views.
If you are on Oracle 12c you might look at DBMS_UTILITY.EXPAND_SQL_TEXT, though you'll probably want to clean up the output a bit for readability.
A few things first
1) A view is a predefined sql query so it is not possible to insert records directly into it. Even a materialized view which is a persistant table structure only gets populated with the results of a query thus as things stand this is not possible. What is possible is to create a new table to populate the data which is currently aggregated at view D
2) It is very possible to aggregate data at muliple levels in Informatica using combination of multiple inline sorter and aggregater transformations which will generate the data at the level you're looking for.
3) Should you do it? Data warehousing best practices would say no and keep the data as granular as possible per the original table A so that it can be rolled up in many ways (refer Kimball group site and read up on star schema for such matters). Do you have much sway in the choice though?
4) The current process (while often used) is not that much better in terms of star schema

How to create lines/stops relationship

I'm not a database expert and I'm simply building a prototype app, so nothing really important.
Anyway, the app is about a subway: this subway has many lines and sometimes some stops are shared between lines (so, for example, stops 3 and 4 are stops of lines 2, 7 and 9).
So, I made up a SQLite stops table:
+---------+-------------+------+
| Field | Type | Auto |
+---------+-------------+------+
| id | integer | YES |
| name | varchar(20) | NO |
| lines | ? | NO |
+---------+-------------+------+
What's the best way to deal with shared stops? My idea was to create a lines table and then in the lines field of the stops table put a comma separated list of lines.id. I don't know why, but I feel there could be a better way.
Any suggestion is appreciated, and sorry for the really noob question.
I would keep it simple and use a table lines which has an ID (primary key) along with other metadata for a line (such as name):
lines
(id, name)
Then, create a table for the stops:
stops
(id, name)
Finally, you can create a bridge table which will connect lines with stops:
bridge
(lineId, stopId)
Each record in the bridge table represents one line having a given stop.
Note that using CSV to represent a line having multiple stops is totally not the way to go here, as it renders the powers of your relational database useless.
Update:
If you want to record the position of a stop in a given line (and assuming that positions would differ across lines), you could use the following table:
stopNumbers
(lineId, stopId, stopPosition)
The stop position can be obtained knowing the line's ID and the stop's ID.
You need a many-to-many relation, which is stored in a separate table like this:
table lines_to_stops
line_fk
stop_fk
That's the relational world ...
Note that records in the database are not in any specific order. If you need to put the stops into any specific order (which you most probably do), you have to store this order to the database as well:
table lines_to_stops
line_fk
stop_fk
order_in_line

merge two datasource to gridview?

what is the best way of doing?, i have one table that returns one set of data and another table that returns another set of data, so in my gridview i want to display
id,name = dataset1
registration_id, registration_name = dataset2
gridview looks like this:
id | name | reg_id | reg_name |
Best bet is to use a JOIN when selecting the data from the database.
If that's not possible, there are several ways to accomplish this with DataTable objects in memory...
One possibility is outlined here: http://msmvps.com/blogs/shahed/archive/2009/02/09/asp-net-tips-display-resultset-from-multiple-datatable.aspx This is how I usually do it if I absolutely can't just get it directly from the server in the format I want.
You can also do it using Linq
An example of a JOIN with LINQ can also be found here: http://www.vbdotnetheaven.com/UploadFile/ShahanDev/4601/Default.aspx
Edit - added based on comments
Based on your comments, I'm not sure that joining the results in a gridview is necessarily what you want. In a one-to-many relationship you will get duplicaiton from the "one" side.
If I'm guessing right, what you really want is something that more accurately represents the one-to-many relationship so instead of data that looks like this:
id | name | reg_id | reg_name |
1 |abs | 1 |adad |
1 |abs | 2 |sadsd |
you really want it to look like this:
1 abs
1 adad
2 sadsd
In that case, you're better off looking into Nested Repeaters: http://support.microsoft.com/kb/306154 or another way to represent heriarchical data.
I think in addition to all the great previos methods , you can write a stored procedure,which contains your logic (you can use temporary tables #table),make it the grid view data source..i use stored procedures many times when i need data from many tables to avoid complex joins and nested controls which may cause low performance according to what i know.
if u mean u use two data sources for the same grid view but the source changes according to some condition , this will help u ..
gridview with more than one data source

What's the best way to retrieve this data?

The architecture for this scenario is as follows:
I have a table of items and several tables of forms. Rather than having the forms own the items, the items own the forms. This is because one item can be on several forms (although only one of each type, but not necessarily on any). The forms and items are all tied together by a common OrderId. This can be represented like so:
OrderItems | Form A | Form B etc....
---------- |--------- |
ItemId |FormAId |
OrderId |OrderId |
FormAId |SomeField |
FormBId |OtherVar |
FormCId |etc...
This works just fine for these forms. However, there is another form, (say, FormX) which cannot have an OrderId because it consists of items from multiple orders. OrderItems does contain a column for FormXId as well, but I'm confused about the best way to get a list of the "FormX"s related to a single OrderId. I'm using MySQL and was thinking maybe a stored proc was the best way to go on this, but I've never used a stored proc on MySQL and don't really know the best way to go about it. My other (kludgy) option was to hit the DB twice, first to get all the items that are for the given OrderId that also have a FormXId, and then get all their FormXIds and do a dynamic SELECT statement where I do something like (pseudocode)
SELECT whatever FROM sometable WHERE FormXId=x OR FormXId=y....
Obviously this is less than ideal, but I can't really think of any other way... anything better I could do either programmatically or architecturally? My back-end code is ASP.NET.
Thanks so much!
UPDATE
In response to the request for more info:
Sample input:
OrderId = 1000
Sample output
FormXs:
-----------------
FormXId | FieldA | FieldB | etc
-------------------------------
1003 | value | value | ...
1020 | ... .. ..
1234 | .. . .. . . ...
You see the problem is that FormX doesn't have one single OrderId but is rather a collection of OrderIds. Sometimes multiple items from the same order are on FormX, sometimes it's just one, most orders don't have any items on FormX. But when someone pulls up their order, I need for all the FormXs their items belong on to show up so they can be modified/viewed.
I was thinking of maybe creating a stored proc that does what I said above, run one query to pull down all the related OrderIds and then another to return the appropriate FormXs. But there has to be a better way...
I understand you need to get a list of the "FormX"s related to a single OrderId. You say, that OrderItems does contain a column for FormXId.
You can issue the following query:
select
FormX.*
From
OrderItems
join
Formx
on
OrderItems.FormXId = FormX.FormXId
where
OrderItems.OrderId = #orderId
You need to pass #orderId to your query and you will get a record set with FormX records related to this order.
You can either package this query up as a stored procedure using #orderId paramter, or you can use dynamic sql and substitute #orderId with real order number you executing your query for.

Resources