Using core/model database with small changes on different installations for customization without duplicating code - sql-server-data-tools

As an example core database looks like this:
Person - Id, FirstName, LastName
Address - Id, Street, ZipCode
This model is used on the majority of the installations but for a couple of installations I want to add customized columns, let's say the column State to Address for Customer X and BirthDate to Person for Customer Y.
Now, I don't want to add these columns to the core database because the State column is only used by our US customers and the BirthDate is only used by our European customers were BirthDate is obligatory (NOT NULL) and would therefore need a dummy value for all the other customers.
I was checking in GitHub about having several branches - Core and US-Customer - but that would mean that the whole Core solution would be copied over to the US-Customer branch but when the Core branch is changed it would not update the US-Customer branch i.e. having to maintain basically two repositories.
Is it possible to have this sort of customization either in SQL Data Tools or in GitHub were the customized solutions (e.g. US-Customer) would only have the absolutely necessary changes and without SQL Data Tools throwing errors in Visual Studio about missing tables or any other error?
Example:
Core branch
Person - Id, FirstName, LastName
Address - Id, Street, ZipCode
US-Customer branch
ALTER TABLE Address ADD State CHAR(2) NOT NULL
EU-Customer branch
ALTER TABLE Person ADD BirthDate DATE NOT NULL

There is no very easy way of implementing so. If you wish to do that completely in SSDT way, then you need to create several projects:
ProjectCore --> will have all shared objects. It shouldn't have references to the projects below;
ProjectUS --> will have all the objects for US and reference ProjectCore as The same database;
ProjectEU --> will have all the objects for EU and reference ProjectCore as The same database.
Both ProjectUS and ProjectEU will have their own publish profiles. You'll have put full definition of different objects there, not just ALTER statements.

Related

What's the best way to store users in DynamoDB so I can get one efficiently, and a related group as well?

I have users for my website that need to log in. In order to do that, I have to check the database for them, by email address or a hash of their email.
Some of my users have an online course in common.
Others are all on the same project.
There are multiple projects and courses.
How might I set up my table so that I can grab individual users, and efficiently query related groups of users?
I'm thinking...
PK = user#mysite
SK = user#email.com
projects = [1,2,3]
courses = [101,202,303]
I can get any user user with a get PK = user#mysite, SK = user#email.com.
But if I query, I have to filter two attributes, and I feel like I'm no longer very efficient.
If I set up users like this on the other hand:
PK = user#email.com
SK = 1#2#3#101#202#303
projects = [1,2,3]
courses = [101,202,303]
Then I can get PK = user#gmail.com and that's unique on its own.
And I can query SK contains 101 for example if I want all the 101 course students.
But I have to maintain this weird # deliminated list of things in the SK string.
Am I thinking about this the right way?
You want to find items which possess a value in an attribute holding a list of values. So do I sometimes! But there is not an index for that.
You can, however, solve this by adding new items to the table.
Your main item would have the email address as both the PK and the SK. It includes attributes listing the courses and projects, and all the other metadata about that user.
For each course, you insert additional items where the course id is the PK and the member emails are the various SKs in that item collection. Same for projects.
Given an email, you can find all about them with a get item. Given a course or project you can find all matching emails with a query against the course or project id. Do a batch get items then if you need all the data about each email.
When someone adds or drops a course or project, you update the main item as well as add/remove the additional indexed items.
Should you want to query by course X and project Y you can pull the matching results to the client and join in the client on email address.
In one of your designs you're proposing a contains against the SK, which is not a supported operator against SKs so that design wouldn't work.

Allowing user to create new data types with custom properties

I am working on a web project where the user should be able to create custom types of merchandise containing any amount of properties of different types (numbers, text, etc). E.g: a box, which has name, price and physical dimensions, and a bottle, which has name, price, and volume.
What would be the best way to represent this in code and in the database?
My first idea was to create a basic template for a piece of merchandise, and dump all the custom data in a single field as stringified JSON. The downside is that this data couldn't be used for IQueryable search, filtering, sorting.
I can also think of creating a separate table, in which I'd store all the custom fields of all merchandise, and referencing them via relations. Wouldn't this, however, cause problems with scaling, as I will be essentially storing all custom properties everywhere in a single table.
Is in the best way to do it? There is no way to create new classes and database tables on the fly in .NET Core, of course, but what other options there are?
Thank you for your time,
I'm doing this in my current side project, and I've done it in the past as well. Basically, you will have a base Product table (or whatever you want to name it). Then you also have tables such as ProductAttributeType and ProductAttribute.
The base Product table would contain attributes common to all products, such as Name and Price.
ProductAttributeType
ProductAttributeTypeCode VARCHAR(10)
AttributeTypeName VARCHAR(50)
Where ProductAttributeTypeCode contains a short / abbreviated code for the attribute type (e.g. "BOOL"), and AttributeTypeName is a friendly name (e.g. "Boolean" or "Yes/No").
ProductAttribute
ProductId INT -- Foreign key to Product table
ProductAttributeTypeCode VARCHAR(10) -- Foreign key to ProductAttributeType table
AttributeName VARCHAR(100) -- The name of the product attribute (e.g. "Volume")
AttributeValue VARCHAR(MAX) -- Contains the actual value of the product attribute
Product has a one-to-many relationship with ProductAttribute.
This is the approach I've taken in the past, as well as in a current project, and it works pretty well. It appears to be a pretty common approach for solving this sort of problem. The only "downside" I can think of is that you need to make sure that the value in the ProductAttribute.AttributeValue column matches the appropriate type for ProductAttributeType(Code). If you design your code properly, and it's well thought out, it's really not so bad, in my opinion.

Asp.net Multi Tenancy implementation on existing solution

I have an asp.net MVC solution, Entity Framework code first, which has dozens of database tables all designed around a single company using the solution.
The requirement has come up to allow multiple companies to use the solution, so what we have done is add "CompanyID" as a column to all database tables and set a default value. There is a company table with the various company names and CompanyID's. On login the user selects the company they are logging in as which stores the CompanyID in the session.
At the moment every Entity Framework call now has to be updated to include the CompanyID, for example when selecting Employees I am doing:
List<Employee> employees = db.Employees.Where(x => x.CompanyID = Session.CompanyID).ToList();
As you can see it will be tedious to do this on thousands of calls to the db. Any update, save, and fetch has to change.
Surely I am doing it the long way and there is a way at runtime, globally to append all DB calls to include the CompanyID stored in the logged in users Session? Something that dynamically appends the CompanyID when fetching values or storing etc? Perhaps a package I can use to do this task at runtime?
In my opinion, there is no need to add CompanyID to EVERY table in the database. I would select just "root" tables/entities for that. For example, Employee or Department clearly sounds like a many-to-one relationship with a company - so adding CompanyID there sounds right. But, for example, EmployeeEquipment which is a many-to-one relationship with Employee does not have to have CompanyID column since it can be filtered by the joined Employee table.
Regarding your request to filter by CompanyID globally, I'm not aware of anything that can do that per request. There are global filters for Entity Framework, but I'm not sure how you can apply them per-request. Take a look on .HasQueryFilter() during model creation if you are using Entity Framework Core.

Best method to retrieve Active Directory list using ASP.NET

I am fairly new to ASP.NET programming. I am designing a web project which will maintain employees information, such as the approval schema, staff inventories, claims, etc. The database will record the employee ID as the key. Currently there is no local table storing the mapping of the employee ID and employee name. These information will be retrieved from the Active Directory.
The new system will allow user to do employee lookup e.g. based on name or ID and generate report e.g. list of employee claims of the month. The lookup can be achieved by directly accessing the AD but I don't think it's a good method for generating list of employees/reports. Hence, I'm planning to download the AD list to local database.
My questions are:
1. Is downloading AD list to local database the right method for this situation? Is there any other alternatives to achieve this?
2. Shall I go with downloading the AD list, how to update it on regular basis? I can only think of clearing the table and reimport the whole list again.
Any advises will be much welcomed.
take a look at http://linqtoad.codeplex.com/ I've used it before with great success
"The new system will allow user to do employee lookup e.g. based on name or ID and generate report e.g. list of employee claims of the month."
Sounds like you do not need all employees from AD at once. In that case I would not download the AD list at all, as that would put you in a situation where you have to deal with your database being out of date.
Just start with retrieving the data from AD on request and only think about optimizations if you encounter performance problems.

LINQ to Entities, several one-to-one references to the same tables and naming

I've started porting a .NET SQL Server application to LINQ to Entities. I have (among others...) one table called Users, and one called Time. Time is reported on a specific user (UserId), but it is also recorded which user made the report (InsertedByUserId) and possibly who has updated the Time since insert (UpdatedByUserId). This gives me three references to the table Users.
When I generate a .EDMX from this I get three references to the table Users: User, User1 and User2. Without manual edit I have no way of knowing which one refers to the UserId, InsertedByUserId or UpdatedByUserId field.
How do others solve this? Maybe it's not necessary to register ALL references, and stick with InsertedByUserId and UpdatedByUserId as ints?
(The manual edit wouldn't be a problem if the database were never updated, but as we make changes to the database every now and then we occasionally have to regenerate the .EMDX, thus removing all manual changes.)
Thanks in advance!
Jos,
Generally when I make my foreign keys, I name them accordingly. From the Entity designer you can differentiate between the different Navigation Properties (ie User, User1, User2) by looking at the FK association (as long as you named your foreign keys distinctly). For Instance I have a ModifiedById and CreatedById field in each table. Both fields reference my SystemUser table, My foreign keys are named like this: FK_[TableName]_SystemUser_CreatedBy and FK_[TableName]_SystemUser_ModifiedBy.
You should notice that in the Navigation properties you can see the Foreign key. You can also modify the name of the Navigation Property (which is in the Conceptual Side "CSDL portion" of the EDMX), and this change will stay when you update your EDMX from the database.

Resources