If i have a field in my db which clarify the type of the application .
takes two values 0 or 1
0 for web app and 1 for win app
and now there is some requirement in my business:
There are some win applications available to all users and some of
them belong to specific users .
What 's the best solution to handle this case .
adding new field to state whether it's public or private
or just adding new value to the same field say 2 to state it's private win app
If you haven't already it would probably be best to slip in a user, role, permission based security model to the database/system, thereby giving you the ability to specify a group of users that have access to a particular application, whether it be web or windows based
I'd say add a new column next to your AppId called PublicIndicatior
Oh and be sure to have a lookup table so people can see what 0 or 1 means, and foreign key it to your data table
Lookup Table:
AppTypeId, AppTypeDescription
0, WebApp
1, WinApp
Data Table:
Id, AppTypeId, PublicIndicator
1,0,1
etc
As Pope suggested above (I +1 him), the best scenario is to add in a new user table (or tables for roles etc if possible) and then link to that through either a new foreign key, or using the appid (assuming it is on your table and unique). Then when the boss comes back 3 weeks later and say, "that's great, but now can we restrict App99 to just the Accounts Dept" you are not going back to the drawing board.
Related
I have a DB table which records changes made to orders. One of the properties on the order object is the ID of the administrator. When an administrator goes out-of-office they have the option of assigning a replacement; the replacement can then assign someone to replace themselves, who can then assign a replacement...
Each time a replacement is assigned the order is updated and an audit trail is created in a DB table named audit_log.
When an administrator returns to work they can remove their replacement, which should then cause their orders to be reassigned to them. This seems a simple problem but I'm having trouble with the logic behind deciding which orders should be reassigned. For example, take a look at the image below...
Now look what happens if Admin 1 returns...
...so far so good, but if Admin 2 then returns...
...Admin 2 would be mistakenly reassigning an order from Admin 1 because the audit log shows that Admin 2 had previously reassigned it to Admin 3 prior to leaving the office. But that order shouldn't be reassigned from Admin 1 to Admin 2 - it belongs to Admin 1 and Admin 1 is not out-of-office.
Consider the scenario where the order gets reassigned through 5 different administrators, then Admin 3 returns and reclaims the order from Admin 5; if Admin 4 then returns they should not be assigned the order, but if Admin 1 or Admin 2 returns then they should reclaim the order from Admin 3.
What this needs is a way of graphing the changes in assignment, then detecting which orders have been assigned ahead of a user but not behind a user, where...
ahead of = a user who is to the right of a context user in the above images (Admin 3 being ahead of Admin 2)
behind = a user who is to the left of a context user in above images (Admin 1 being behind Admin 2)
...but I just don't know how to build this? Are there any well-known algorithms or patterns from building such a graph, and any pointers as to how to implement such in C#?
Some additional information: The records in the audit_log DB table also have id and recorded (DateTime2) fields, so they can be retrieved in chronological order.
I´m developing a loan administration application. I have a table/entity named Loan where I save them all. What I need, is to save the invoiced loans with an autoinc (1, 2 , 3, 4, 5, 6, etc) and to have another autoinc sequence to save all those loans not invoiced (example: 20000, 20001, 20002, etc). The idea is to have both loans in the same table, but with different IDs, then, based on a state, invoiced or not invoiced loan will appear. The application is already in its final stage, so using 2 different tables to save each one of them is not an option. I need advice to find a solution and see if this can be done. By the way, I´m using Entity Framework 4 with C#.
Basically, in a few words, I need to create 2 autoinc sequences for one field of the table. The 2nd autoinc number must start in a high number so as to not be reached by the first one.
Hope somebody can help me out..
EDIT:
Guys, I want to elaborate more about the problem because I don´t know if you are getting the point of doing this. The idea of the not invoiced loans is to let the user to give loans "illegaly" without paying taxes for it. Thats why it should be differentiated. I just cant use one id sequence number because if some inspectors looks at the id number would say, "Ok, here we have loans 1, 2, 3, 7, 8, but where is it 4, 5, 6?" The idea of having two sequences one a lot higher than the other, high enought to not be able to reach it by the first, was to achive that. Using the same sequence, but having another field to differenciate if it´s invoiced or not can be a possible solution, but as I have many users, I liked how SQL automatically sets the id of the loan.
As Greg has mentioned, first of all, you will need to turn off auto incrementing on the table. Then create a stored proc that you will call from the data access layer, which will create two records on the table by calculating the correct Ids. This way the data access layer and the business logic will be agnostic to the db-level task.
And as again pointed out by Greg, have a strategy in place to handle the situation when the number of applications reaches 20K mark.
If you don’t mind me asking, why did you select the approach of basing state on a primary/candidate key? Why not maintain a column just to say whether the loan is invoiced or not? Since you are using EF, if you take this approach, you should be able to use Table per Hierarchy to project two sets of data based on the discriminator key (http://www.c-sharpcorner.com/UploadFile/ff2f08/entity-framework-4-0-tph-part-2/ and
http://weblogs.asp.net/manavi/archive/2010/12/24/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-1-table-per-hierarchy-tph.aspx)
Or.. why not query the invoice table, if available (sub query or join) to figure out whether a loan is invoiced.
Cheers
My current schema looks like the following:
ID | DisplayVal
-- ----------
1 1-H-3
2 2-H-3
3 3-J-4
In the above, the ID field is an IDENTITY INT field which is also used as and end user account Id. The DisplayVal is what they see on the screen.
A new client has provided their own Account Id values, but they are alpha-numeric, so they can't just go into the IDENTITY field. Here are my scenarios: I am looking for a scenario that would offer the best maintainability, end user experience, magnitude and impact of changes and testing/QA impact.
My first scenario was to add an Account Number column that would be a VARCHAR(x) and accommodate all types of Account Numbers. It would look like this:
ID | DisplayVal | AccountNumber
-- ---------- -------------
1 1-H-3 1
2 2-H-3 2
3 3-J-4 3
4 h389 h389
5 h-400-x h400
In the above, in the case of the first client, the seeded Identity which is the Account Id would be copied into the Account Number, but for the other client, there would still be a seeded Identity created, but their Account Number would be different and it may or may not match the Display Value.
My second scenario was to not add any columns and for clients that provide an Account Number, I would turn off IDENTITY INSERT and insert the new Id's and then turn identity insert back on. If a client did not provide an Account Number, I would auto-generate one, obviously trying to avoid collisions.
The third scenario was basically to leave the new Account Number as a legacy Account Number and create new identity values for all new records. This would require the end-user to become familiar with a new Account Number. It is probably the easiest, but not sure if there are any downsides.
If there is another scenario you know that would work well in this case, let me know.
You should not use business keys, like account id, as identity. Create a new id column and populate it either using an autoincrement field or a guid. Your users or other systems that interact with your system should not know/depend on this value.
I'm creating a maker-checker functionality where, maker creates a record and it is reviewed by the checker. The record creation will not happen until the checker approves it. If the checker rejects it then it should be rolled back.
The idea which i know is create a temporary table of records which will hold the records to be created until the checker approves it. But this method will have 2X number of tables to be created to cover all functionalities.
What are the best practices to achieve this?
Is it something which can be done using Windows Work Flow.? (WWF)
Just add a few more columns to your db.
Status : Current status of record ( Waiting for approval, Approved,
Declined . etc)
Maker : Username or id
Checker : Username or id
Checker Approval/Rejection Time
Alternatively if you have lots of tables like this needs to maker/checker workflow you can add another table and reference all other record to this table.
Windows workflow foundation also could work for you but i persnoally find it difficult to use
If you want revisions for the recored you also need more columns. Such as Revision Number and IsLastRevision.
I dont know what you are using for accessing db and modifiying records. If you are using OR/M you might override Update and do revisions on all saves . For Example
void Update(Entity e )
{
Entity n = new Entity();
// Create a copy of e ( With AutoMapper for example or manually )
e.Current = true;
e.RevisionNumber += 1;
Update(e);
Insert(n);
}
In this case you will have two options:
Create two identical tables and use one table for approved data and one for requested data.
OR
You can create two rows for a user with TypeID(requested/approved). in this case user will create a request with typeID = requested when approver approved that request you simply override current approved record with new one otherwise simply mark requested row with rejected status.
My question is :
I have a domain table in database, where I add some rules for users.
Something like this:
Table UserRoles:
idRule cRuleDescription bRuleIsActive
1 Edit client true
2 Delete client false
My C# application refers to this table using enumeration, like this :
public enum UserRoles: int
{
CanEditClient = 1,
CanDeleteClient = 2,
CanChangeClientName = 3,
//More code
}
And I use a C# method that query the database, by its Id, to know if the logged user has permission for some action. Something like this:
bool HasPermissionToEdit = Rules.UserHasPermisson(UserName, UserRoles.CanEditClient)
if(HasPermissionToEdit)
{
//Do the work!
}
But using this gives me some trouble. Someone created new rows in a production eviroment on database. And the ids are not correct anymore. And I'll need to change the enumeration on my C# code. I need to use this table because, administration users can manage the rules for other group of users.
How do you work with it? There is a better way to reference a registry on a table?
If you want to implement this properly, make the key contain the name of the role. That way, there cannot be accidents with the ID's where someone thinks the key is meaningless. Naming it idRule does not help.
Second, add a check constraint to enforce correct usage of role names.
Third, add a unique key constraint on the name of the role to enforce that each role only occurs once.
You can use string enums to convert from the role names to integers if you want to. See C# String enums for a nice design pattern.
Example table:
ID - NAME - DESCRIPTION - IS_ACTIVE
1 - CanEditClient - client - true
2 - CanDeleteClient - client - false
3 - CanChangeClientName - client - true
Then make sure to add a unique constraint to NAME and a check constraint as well.
Now, no matter how someone shuffles the ID's, your code will continue to work.
Using the rule ID to map to an enum is not crazy in itself as long as the rule ID is not automatically generated (i.e. not an identiy column).