Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am creating a web app using ef core, and I have three entites, Student, Teacher, and Project. Now each of these tables needs to have multiple Links (Id & Url columns here) that point somewhere on the web. What is the best way to design this relation.
I've thought adding a StudentId, TeacherId, and ProjectId nullable column to the Links table. I've thought of creating a Links table for each entity. I've also thought of using a discriminator column, but still, it doesn't feel right.
How do I properly design this?
Note: The Student and Teacher table have a one to one relation with a user table, so I could just put the foreign key there, but the Project table is unrelated to these.
Based on the comments the link, you have a set of links for some or each of your entities in question.
But these are attributes, even a link array is an attribute of those entities, as a link is not an entity on its own. Unfortunately, 1NF requires each attribute to have a unique value. But let's be serious: is this an unbreakable constraint? Of course not. Some RDBMS do have array columns. SQL Server does not. But it has XML and JSON column types. EF has some other tools to provide the same.
Actually it depends on what do you want to do with those links: are they somehow processed with SQL or not. If only the upper tiers are handling them - and I suppose they are processed on the visualization tier - from the database point of view the link array is a single attribute.
If those links are passing trough your business logic, and they are only used during rendering, you can simply store them as comma-separated lists, or JSONS text in a nvarchar with a string property counterpart in the EF entity class, and split/parse them only on the visualization tier. That would make the less concentrated effort.
If your business logic needs them separately, EF does have support for complex types. You can still store your arrays as JSON text in a nvarchar column and serialize-deserialize them transparently. Check here: https://www.codeproject.com/Articles/1166099/Entity-Framework-Storing-complex-properties-as-JSO even better solution here: https://entityframework.net/knowledge-base/14779740/can-i-embed-an-object-in-an-ef-entity--serialize-on-save--deserialize-on-access--
SPARSE is still there of course, if applicable.
You can use below three mapping tables. Which are maintain your many to many relationship.
Like: 4 to 5 students working on same link.
2 teachers handling same link.
create table student_link_mapping(slmid int identity(1,1), studentid int not null, linkid int not null)
create table teacher_link_mapping(tlmid int identity(1,1), teacherid int not null, linkid int not null)
create table project_link_mapping(plmid int identity(1,1), projectid int not null, linkid int not null)
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 days ago.
Improve this question
Context:
I am writing a web application using SQL server database, C# MVC API layer, Next (React) front end. The database is already created and populated and is in full Third Normal Form (3NF) and the base entity classes have been autogenerated from the database, so using a database-first modelling approach. This will seem like a bit of a rant, but I want to know if I am approacing this correctly because it feels like an awful lot of boiler plate code but this may just be because my project is not big enough to reap the benefits.
These aren't my tables but the relationship is the same; namely 1:many relationships with a primary key of ParentTable.id and foreign key of ChildTable.ParentTable_id
Consider a system with 4 tables: Store, Customer, Order, OrderLine. Each customer belongs to only one store and each order belongs to only 1 customer. The base models have their respective links (1 Parent => N Children) and Inverse Link (1 Child => 1 Parent). When you call the .../api/store it doesn't contain any customers by default. If you modify the controller
_context.Stores.Include("Customers").ToListAsync()
This throws an error when returning it as JSON because of the cyclic link so I need to create ViewModels for both the Customer (exluding the Stores model, but just keeping the storeID) and for the Store (including the collection of CustomerViewModel). This is fine while this is the only VM I need for customer or store but what if I also need a customer view model that includes the orders, or a viewmodel for the marketing team and a different one for the finance team. What options do I have? I am thinking either different model names within the same namespace
StoreCustomerViewModel
FinanceCustomerViewModel
MarketingCustomerViewModel
or using namespaces
using ...models.finance -> CustomerViewModel
using ...models.marketing -> CustomerViewModel
Or am I thinking about this the wrong way? If I need to combine models (e.g. where the main model contains a collection of other models - Customer.orders = List-OrdersViewModel) can these cut across namespaces and if so how and what are the caveats around that.
I'm not sure but once I stumbled upon a similar problem (Eager Loading).
Some advised to use [JsonIgnore] above the properties I don't want.
others advised to add UseLazyLoading() in my program.cs
But what really worked for me was creating DTOs and using AutoMapper.
So try out each option and see what works for your project.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I am working on a project for college and stumbled upon a problem which I am not sure how to handle it in a best way.
I have a SQL Server database that is manually created, and a Winforms project in Visual Studio written in C#. The application should do CRUD operations on database.
My question is what is the best way for manipulate the primary key columns in the tables? Should I define them in database as auto increment integer and let the database management system to handle the primary keys or should I define them just as int and populate them programatically within Visual Studio project, and if so how to do it?
I am not looking for complete solution, just for hint what is the best way of doing this.
I am very much a beginner, so please be gentle...
In general, auto-incremented (or identity or serial) primary keys are the way to go. You don't generally want your application to be worrying about things like whether the values have been used already.
If your application is multi-threaded -- that is, multiple users at the same time -- then the database will take care of any conflicts. That is quite convenient.
I am a fan of surrogate keys created by the database. In databases that cluster (sort) the rows by the primary key, it is much more efficient to have an automatically incremented value. And the database can take care of that.
There are some cases where you want a natural key. Of course, that is also permissible. But if you are going to invent a primary key for a table, let the database do the work.
When defining structures for DB backing for CRUD operations, you need to ask yourself:
Does it matter that my primary key is highly predictable?
By that I mean, if I am launching a user to a screen such "whatever.com/something/edit/1"
Aside from obvious security, does it help or harm the business process that a user can manipulate the url and inject 2 or 3 or 4 into path?
If it doesn't matter then absolutely set it as auto increminitng int on the DB side and offload that area of responsibility to the database to handle. You now no longer have to highly concern yourself with dealing with key generation.
IF it does matter then set the primary key as a unique identifier. In code when adding a new record set then you will generate a new GUID and set that as the primary key (Guid.NewGuid()). This would prevent the user from traversing your data in an uncontrolled manner as randomly guessing GUIDs would then be problematic to them. EX:
New path: "whatever.com/something/edit/0f8fad5b-d9cb-469f-a165-70867728950e"
Not saying that it is impossible to stumble upon things but the regular person using your application would not be so inclined to go exploring with url manipulation since they would be wasting 99.99% of their time with invlaid posts trying to guess a valid GUID that is registered in your DB.
As an added comment, if you decided to keep the primary key as a int and not use auto-increment then you are just setting yourself up for a ton of unnecessary work where I have never personally ever seen any real return on investment for the logic you would right to check if the placeholder is already used. That and think about tracking history? You would be settings yourself up for a world of pain if you ever decided to remove records from the table and then reuse them. That is a whole other set of concerns you would have to manage on top of what you are doing.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
I have different product types that have different attributes. They cannot be stored in a single table as the attributes are too distinct. There's a couple of options I'm currently looking at: EAV and a table for each type.
My situation is, at the moment, there are only a number of types (lets say 8) but in the near future with almost 100% certainty, this can grow. But the growth is controlled by me, its not defined by users. It will be up to me to grow the product type.
I'm currently inclined to use EAV (for the reason that I can cover the growth easily - I think) but I am not sure as I'm concerned with the performance as well as modeling them in my language of choice (C#). My question is, given the scenario above, is it better for me to create a single table for each product type and add as necessary, or would this be a good case (or not even good, lets say acceptable) to use EAV?
There's no short good or bad answer to this concern, because it depends of many things.
Do you have a lot of product types ?
How do you think each of them will evolve (think to what will happen when you will add new fields to products) ?
Do you need to handle "variants" of the products ?
Do you intend to add entirely new types of products ?
Etc.
EAV is probably a good way to go if you answer if you answer "yes" to some or all these questions.
Regarding C#, I have implemented in the past an EAV data catalog with it, and using Entity Framework over SQL Server (so a RDBMS).
It worked nice to me.
But if you need to handle a lot of products, performance can quickly become an issue. You could also look for a "NoSQL" solution, did you think about it ?
Just keep in mind that your model object does not have to match your data model.
For example you could perfectly have a stronly typed object for each type of product if you need so.
Much depends on the operations that will be performed on entities. If you will:
often add new attributes to products;
add a lot of products type;
implement full product type search (or other "full product type" feature);
I recommend you to use EAV.
I have implemented in the past EAV data structure with ADO.NET and MS SQL and don't have any problem with performance.
Also, Morten Bork above recommend use "sub types". But if you want implement some "full product type" features, I think it will be more difficult then use pure EAV model.
EAV doesn't really play well with a relational database. So if that is what you are doing. (IE connecting to SQL) Then I would say no. Take the hit in development time, and design a table pr type of product, or make a aggregate table that holds various properties for a product type, and then connect the properties to the relevant tables.
So if a product contains "Cogs" then you have a table with "teethcount", "radius" etc.
Another product type has "Scews" with properties "Length", "riling" etc.
And if a product type has both cogs and screws, it merely has relation to each of these subtypes.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
With the risk of being labeled off-topic I am going to ask it any way :-)
I recently joined a new development team and they do have a habit of doing the following. While I have always considered it an anti pattern I just find out that I can't explain why. So, I am just curious to get your opinions.
Let consider the following situation: You have an invoice application, when a new invoice needs to be created, it has to get a new unique invoice number (like INV0001). Of course, it will be stored in the DB, in a table having an auto increment field 'id'. So, just generate the Number from the id.
class Invoice{
[Key]
int Id { get; set;}
string Number => String.Concat("INV", this.Id.ToString().PadLeft(4, '0'));
}
I have always (blindly) obeyed the rule "don't use an id as a business value". but I can't really motivate it.
don't use an id as a business value
You can apply same explanation which used for motivating of Separation of concerns.
If in business logic code you are using features of implementation details of Id, for example generated by database, this mean that your business logic depend on database implementation.
Id have one responsibility - provide unique value, by which you can identify entity and link it with other related entities. So in your business logic you can use Id value only for equality conditions.
For example if you have Id of type integer generated by database.
And you have somewhere in the business logic condition
if (Id == 0)
{
return "new";
}
Your business logic will depend on Id implementation (type). Which mean you can use only Id of value integer and can not change it to Guid for example.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I am trying to develop a form with asp.net Webform and would like to display in a ListBox or checkbox data from SQL Server. So I can call the elements of the table, there is no problem. But the worry is that I'd like to stored information that the user has selected / chosen the form in a different table because in the future I would like someone developer can not change the elements of the form without touching the code but just touch Sql server management Studio.
I hope you understand my problem ... Do you have a solution?
Thank you for your help :)
You can create a master table where all your master data resides. Ex. list of languages to be shown in Checkbox or Listbox.
And there will be another table which holds the user inputs usually referencing the Ids of master data along with other user inputs.
Ex.
Languages -> master table
-----------------------------
LanguageID
Name
UserDetails -> detail or actual table where you can store your user's inputs as well as the LanguageId from language table
-----------------------------
UserId
Name
City
LanguageID -> foreign key which reference of Language table
Hope this will help you.
I believe I understand what you're after.
Typically the way to do this is to have two tables in your database.
Options
- OptionID
- OptionName
// maybe an isactive flag?
Responses
- ResponseID
- OptionID
// maybe a username?
Your form then shows all the active options on the page. When a user comes along you create a response row where the OptionID is set to the ID of the option the user chose (with an appropriate foreign key).
Your developer can then add and deactivate options without removing users' responses.