I need an idea. I have an app, a winform having multiple tabs in it. There are a bunch of people using it, but none of them needs to use all the tabs, just a couple of them. I've reached a point where it's hard to handle from the source code, so I need a solution to easily manage the permissions. The best would be to use an SQL table for this as I also have to provide for another guy the possibility to modify the rights. I think it would be fine to simply remove the tabs by creating an sql table like this, and at the program startup simply query something like this:
select tabid from table where loggedinuser = 0
and then just loop through the result and remove all of them
foreach(tabid in tabids)
{
tabControl1.TabPages.RemoveByKey(tabid);
}
table:
+----------+----------+-------+-------+-------+
| tabid | name | user1 | user2 | user3 |
+----------+----------+-------+-------+-------+
| tabPage1 | project1 | 0 | 1 | 0 |
+----------+----------+-------+-------+-------+
| tabPage2 | project2 | 1 | 0 | 1 |
+----------+----------+-------+-------+-------+
| tabPage3 | project3 | 1 | 0 | 0 |
+----------+----------+-------+-------+-------+
However I somehow feel that this is not an elegant solution, especially because you have create a new column each time a new guy has to be added. Do you have any idea how to solve it?
I think this is an issue of the database's design, and a basic one; perhaps you need to improve your understanding of SQL databases, particularly relationships and primary/foreign keys. You shouldn't add new columns but new rows.
You need a table for the users, one for the tabs and one to connect the two. Such as this:
User:
+---------+------+
| user_id | name |
+---------+------+
| 1 | John |
+---------+------+
| 2 | Jane |
+---------+------+
Tab:
+--------+----------+
| tab_id | title |
+--------+----------+
| 1 | Articles |
+--------+----------+
| 2 | Products |
+--------+----------+
UserTab:
+---------+--------+---------+
| user_id | tab_id | enabled |
+---------+--------+---------+
| 1 | 1 | 1 |
+---------+--------+---------+
| 1 | 2 | 0 |
+---------+--------+---------+
| 2 | 1 | 0 |
+---------+--------+---------+
| 2 | 2 | 1 |
+---------+--------+---------+
In this example, John can only access Articles and Jane can only access Products.
You should get the ID of the current user and get the entries from UserTab, then remove the tabs that correspond to the IDs for which enabled=0.
You also should make a "default" choice for when the right combination of user and tab doesn't exist in the UserTab table: either display the tab by default or hide it by default.
If you do it through SQL, a simple data model could be :
USER TABLE would have fields user_id,username,... all USER related fields you wish
ROLE TABLE would have fields role_id,role_name
USERROLE TABLE would have fields f_user_id,f_role_id(both foreign keys)
Each record (line) in this table links a user to a role, so a user can have many roles, and a role can be attribuated to many users. That's called a many-to-many relationship
ROLERIGHT TABLE would have fields f_role_id,tabid
Each record (line) in this table links a role to a tab that this role has access to. That means if a role should access all tabs and you've got 10 tabs, you'll have 10 lines with the same role_id and a different tabid from 1 to 10. It is also a many-to-many relationship.
This is quite an usual database pattern for access right management I guess. Now what you have to do is define the several roles. And assign it to the different users. If a new user comes in and he should have the same rights as another user, you just have to assign him the same role(s) as the other user. Depending on complexity and the number of possible tabs/users combinations, you will or not have many roles with few rights, or a few roles with access to several tabs. The latter would probably be the case for a limited number of users, but the good thing is that you could easily scale up without changing the model, only the data.
Related
I have a table that has a key and an alternative key column within the same table. If a value is set in the key column, it must not be used in the alternative key column and vice versa. `
For example, this should be valid:
-----------------------------
| Key | alternative Key |
|---------|-----------------|
| Key_1 | NULL |
| Key_2 | NULL |
| Key_3 | Key_36 |
| Key_4 | NULL |
| ... | ... |
-----------------------------
But this should not be allowed:
-----------------------------
| Key | alternative Key |
|---------|-----------------|
| Key_1 | NULL |
| Key_2 | NULL |
| Key_3 | Key_1 |
| Key_4 | NULL |
| ... | ... |
-----------------------------
The root of the problem is, that my system communicates with a PLC through these keys. However, there are some use-cases where the key we send to the PLC is different from the key we display on screen. The key is always displayed on screen, but if an alternative key is present, it is used for communication instead of the key.
Is it possible to prevent this using SQL constraints or do I need to handle this in my business logic? I am using a code-first approach with C# entities using entity framework core, if that makes a difference. I don't want to change my data-model, if I don't have to.
I agree 100% with the above comments about correcting your data model. Some databases, e.g., Sql Server, support unique indexes on schema-bound views. A view like Select Key From TheTable Union All Select AlternateKey From TheTable Where AlternateKey Is Not Null could then enforce a unique constraint.
For a MVC application I am developing, I need to update the values of certain columns of a table in database every quarter i.e. on 1st day of Jan, Apr, July and Oct every year.
For example, if the table currently looks something like:
+-------+------------------+---------------+----------------+----------------------+---------------+------------+------------+
| EmpId | Experience_Prior | Qualification | Specialization | Status | LastSubmitted | NextDue | ApprovedOn |
+-------+------------------+---------------+----------------+----------------------+---------------+------------+------------+
| EmpId | 0.00 | B.Tech | CSE | Assessment Submitted | 2016-11-20 | 2017-01-01 | 2016-11-20 |
+-------+------------------+---------------+----------------+----------------------+---------------+------------+------------+
Then on the 1st day of next quarter, the columns Status, LastSubmitted, NextDue and ApprovedOn have to be updated as:
+-------+------------------+---------------+----------------+--------------------+---------------+------------+------------+
| EmpId | Experience_Prior | Qualification | Specialization | Status | LastSubmitted | NextDue | ApprovedOn |
+-------+------------------+---------------+----------------+--------------------+---------------+------------+------------+
| EmpId | 0.00 | B.Tech | CSE | Assessment Overdue | NULL | 2017-01-04 | NULL |
+-------+------------------+---------------+----------------+--------------------+---------------+------------+------------+
In case it's unclear, NextDue should be updated to the 1st day of next quarter.
This has to be followed by an email to all users using the application.
I know how to update the columns and send emails from the application. I just need to know how to execute all these every quarter.
The application is an intranet MVC4 application and the database is SQL Server 2008 R2 Express.
You have two options, Use Background job to update it ex(HangFire), But you will have another challenge that you can't use system.net and smtp to send emails as there is no HttpRequest, you will have to use service for sending ex (mailgun) or may be there is a workaround for that !!.
second option, Create a static variables contains last modified dates (or table in db) and check it with Current date everytime you will update, If Ok do your update, send emails, update last modified date again.
Hope that help
Use cronjob or Quartz scheduler that will Schedule and trigger on 1st date of every Quarter to run your Java Program/Application and update the Database columns.
I've spent a bit of time looking at this and cannot find an answer online (Perhaps I am searching for the wrong thing..)
Below is a simplified version of the problem.
I have two tables:
Table 1 : Areas
AreaID | Group 1 | Group2 | Group3
----------------------------------------------
1 | 2 | 22 | 10
2 | 5 | 1 | 9
3 | 4 | 3 | 2
Table 2 : Groups
GroupID | Group | Code | Description
-------------------------------------------------
1 | 1 | 2 | Description 1
2 | 1 | 5 | Description 2
3 | 1 | 4 | Description 3
4 | 2 | 22 | Description 4
5 | 2 | 1 | Description 5
6 | 2 | 3 | Description 6
7 | 3 | 10 | Description 7
8 | 3 | 9 | Description 8
9 | 3 | 2 | Description 9
So the SQL to get the Group description for Area 1 Group 3 would be:
Select g.Description from Areas a
inner join Groups g on g.Code = a.Group3 and g.Group = 3
where a.AreaID = 1
To clarify the Areas table has one Foreign Key linking it to the Groups table, but to get a unique record from the groups table you also need to have the "Group" column.
This is fine using ADO.Net or Stored procs, but we really would like to use EF and be able to navigate between the entities properly.
I also need to point out that for the purposes of this project we ONLY need the Group3 from the areas table, we are not interested in any other groupings at the moment.
Where I am upto:
I have created classes to represent the tables in my project, I have added modelbindings to the context to define a relationship between the Area and the Group based on the Area.Group3 column mapping to the Group.Code column and this works (Its essentially a many to many relationship in EF at the moment) but it also brings out all of the rows for other groups where the Code column matches (Such as code 2 in the example above brings back GroupIDs 1 and 9)
What I would like to be able to do is constrain it in the context by saying something like
modelBuilder.Entity<Area>()
.hasRequired(a=>a.Group)
.WithMany(g=>g.Areas)
.map(m=>
{m.MapKey("Group3")});
but of course the above without a constraint on Group.Group = 3 brings back multiple groups for each Area which in turn breaks because the binding is telling it to expect one!
Thats a bit of a ramble, if anyone needs clarification on the above to be able to help let me know and Ill get the info to you!
Thanks
I want to create a "sessions" table in an SQL database for a school project. Each session should have:
Session ID
Lecturer name
Time and date
Module name
Course name
List of student IDs
List of student statuses(Present, absent, late)
How can I represent such a thing ???
Is it better to create ONE table to represent all sessions, where each session would be one row, and have an array of strings in each column that represents the names, IDs, and status of students??
OR
Create a new table for each new session ??
What is better, and please explain how to do it briefly.
Bear in mind, that I would need to insert/delete/update/view each table from a C# windows application, and the maximum expected number of sessions is just 100.
Also, I am using SQL Server 2012 with a C# windows application developed with Visual Studio 2012
Thanks
I think you should have 3 tables :
Students
------------------------------------
| StudentID | FirstName | LastName |
|-----------|-----------|----------|
| 4456 | John | Doe |
| 6678 | Billy | Bob |
------------------------------------
Here StudentID is Primary Key
Sessions
---------------------------------------------------------------------
| SessionID | Lecturer | DateTime | Module | Course |
|-----------|----------|----------|------------------|--------------|
| 1 | Mr.Joe | 524523461| Natural Sciences | Oceanography |
---------------------------------------------------------------------
Here dateTime would be a Unix Timestamp and SessionId is Primary Key
SessionAttendance
-------------------------------------
| SessionID | StudentID | Status |
|-----------|-----------|-----------|
| 1 | 4456 | 'Late' |
| 1 | 6678 | 'Present' |
-------------------------------------
Here SessionID and StudentID are both Primary Keys
Reason
Here you don't need to parse all the lists of attendance and statuses. The queries may get a little bigger, but it will save you alot of parsing code.
Example Query :
SELECT SessionID FROM SessionAttendance WHERE StudentID = (SELECT StudentID FROM Students WHERE FirstName = 'John' AND LastName = 'Doe') AND Status = 'Late';
It will get all the sessions in which John Doe was late. Simple, right?
Other Comments
You cannot store arrays of information in an database column. It
must be a list that is delimited somehow
In your application, I reccomend you always keep the StudentID with
its FirstName and LastName because it will make queries easier, and
will keep the names localized (so that you can change it in one
place and will change everywhere else)
How to make a blank database for every registered user or it is already implemented in ASP MVC4? Will they have different databases? For example, in an application, which stores contacts, I would like, that different users could create their own contact list.
And if I have ContactsController, which I want only registered users to be edited, should I write something like that?
[Authorize]
public class ContactsController : Controller
EDIT
O thanks Bhushan, I didn't know that User ID will store different data.In Contact table I have ContactId, which is associated with a contact data and it has a primary key, should I add for example UserId in the same Contact table to associate it with registered user ID? And should UserId have primary key?
If I understand your question properly:
different users could create their own contact list
Above task doesn't require a separate database, You can associate Contacts with Users by adding a field ContactOwner or similar name in the Contact table which will store a User ID.
So your contacts table can look like following: (TABLE NAME: CONTACTS)
|ContactID | ContactType | ContactName | ContactOwner |
|0123456789 | MOBILE | Mr. ABC | USER1 |
|email#email.com | EMAIL | Mr. ABC | USER1 |
|0123456789 | MOBILE | Mr. PQR | USER1 |
|0123456789 | MOBILE | Mr. XYZ | USER1 |
|0123456789 | MOBILE | Mr. LMN | USER2 |
|0123456789 | MOBILE | Mr. AAA | USER3 |
So as you can see the sample table above you can identify which ContactID belongs to which User? Or which are the contacts created by which User?
In this case you have to make ContactOwner primary key(Composite key) with other primary key(s), to make sure that one contact can be Owned/Created by multiple Users.
Update 1
To get contacts created by specific user you can write a query like:
Select * from CONTACTS where ContactOwner = 'USER1'
Above query will give you the contacts which are Created/Owned by USER1, and not the ones created by other users. so your result will contain the following records using above query:
|ContactID | ContactType | ContactName | ContactOwner |
|0123456789 | MOBILE | Mr. ABC | USER1 |
|email#email.com | EMAIL | Mr. ABC | USER1 |
|0123456789 | MOBILE | Mr. PQR | USER1 |
|0123456789 | MOBILE | Mr. XYZ | USER1 |
Update 2
Your query will be a dynamic one in which ContactOwner will be the USER who is logged in. This and This might help you to write dynamic query (prepared statement)[Note: since I am a Java developer so I don't know the suitable syntax in C# for writing the dynamic query.]
If you want to have an empty DB for each user, just add as part of the registration process creating new database. you can easily do that with SQL statements (CRATE DATABASE, followed by CREATE TABLE and other create statements to create your schema). you can also use SMO do duplicate existing template databse. you can also create it using entity framework database-first (with few tweaks, like modifying your connection string). BUT, all those options are not recommended for your scenario.
If you want to give each user his contact list, just add to the "Contacts" table "OwnerUserID" column, or something like that, that will have FK relationship to your users table, and will include the user which this row belongs to. In your queries, just filter by this and show each user his own contact list.
This way it'll be much easier for you to manage things and add/modify things in the future. also, working with multiple databases like you asked in your questions will give you a lot of pain, with almost no benefits (in most scenarios).
Best of luck.
FYI, in e.g. SQL Server 2012, the maximum number of databases is 32,767.
Please don't make a new database for every user, it defies basic logic and the point of having relational databases in the first place. Use tables and foreign keys and whatnot.