Entity Framework Code First - Database schema for a catalog with product and product options - entity-framework

I'm trying to create a e-commerce website with out using any third party components.
My biggest problem so far is designing my model/database schema.
The e-commerce solution is for a Take away.
They only really have two types of Meals they Sell.
Rice Meals
Noodle meals Meals
Now Rice Meals have a set of options, so for example a Rice meal comes with either beans or plantain or both. (If both we need to off set the price)
Rice meals also come with a sauce the customer has 3 different options. There is no price difference.
Noodle meals
You can choose a Noodle type
You Can choose a sauce that goes with it.
You can choose if you want fish or meat
Then they have other products that don't have any options.
So my question is how can I create a flexible schema to store Products the options they have and the possible values for those options.
I also need to work out how to store what has actually been selected by the user.
I'm using EF with code first, would love someone to give me a few tips in the right direction.
The closest thing I have come across that may be a solution is this.
http://villyblog.blogspot.co.uk/2008/11/sample-database-schema-for-catalog-with.html
Really confused about the best way to do this.

Keep it simple!
Modeling is a skill. It's about observing and filtering. Even in a relatively simple business like a Take-away there is a lot of noise and if you manage to filter the noise and keep the essence your entity model will become both robust and flexible. First focus on the absolute minimum. Let me try to show you how this could work in your case.
The filtering begins with finding the "ubiquitous" language (Evans, Domain Driven Design): the "things" the business talks about and that are candidates to become entities in the model.
You talk about meals, types, values, prices, discounts, options, products. What are candidate entities?
One important step to take is to find the real, tangible "things". Customers don't eat options. They eat meals, or products. Nor do they eat prices.
"Option" is an interesting word. It is a covert verb. It's an act of opting for some "thing". It's a common design flaw in modeling to turn actions into entities, while they should become methods working on entities. Finding these disguised verbs is very very important. Without diving too deep into this issue I can say that having actions as entities make it hard to assign the right responsibilities to classes.
Likewise, prices (values) and types are no tangible things. They are attributes of things. Turning attributes into entities is a less obvious error, but it happens. I think the model you show as example contains both of the above flaws.
So far, in fact, the only real "thing" that emerges is a Product. The rest is either action or attribute. A Product can either be a meal, or a component of a meal. So these products come in combinations, or aggregates, which can be modeled by a hierarchy.
So here's the core of your "flexible schema to store Products":
You can store all possible combinations of products in one database table. No need to store options separately. Options are products as well. It's an act of combining to design the options in a hierarchy of products.
A concrete part of the hierarchy, the rice meals, could look like this:
The business does the combining, which is designing the hierarchy. The customer does the picking of options. Here business rules come into play. Let's say one rule is that the owner can combine any products, another rule is the customer can only combine end points (the smaller gray rectangles). The parent product could contain a property telling how many of its children can be chosen.
There may be a way to build these rules into the model, but coded rules are far more easy to modify than a model.. Let the model just be a dumb bag of data.
Now the part
I also need to work out how to store what has actually been selected by the user.
When a customer picks options he is making a classical order with order lines. That would make for a model like
Well, this is getting a long answer. A short word on the discounts. It depends a bit on how you want to calculate them. A simple way is a product property that's simply a multiplication factor to apply to the prices of each child product when more than 1 are selected.

Something like this might work, based vaguely on the link you provided:
MealType
- MealTypeID (short maybe? identity, PK)
- Name
Meal
- MealID (long, identity, PK)
- MealTypeID (FK)
- Name
- BasePrice
- IsActive (bit)
MealOption
- MealOptionID (PK) (short or int, identity)
- Name
- PriceOffset
- IsActive (bit)
MealMealOption (not the best name, but just represents a relationship between Meals and MealOptions)
- MealMealOptionID (PK, int or long, identity)
(composite foreign key with MealID and MealOptionID)
- MealID
- MealOptionID
Order
- (this holds stuff common to all orders such as billing address info, messages from the customer, etc.)
- OrderID (long, identity, PK)
- TotalCost
- TotalPriceOffset
etc...
OrderItems
- OrderItemsID (long, identity, PK)
- OrderId (FK)
- MealID (FK)
other order item-specific stuff...
OrderOptions
- OrderOptionID (long, identity, PK)
- OrderItemsID (FK)
- OrderID (FK)
- MealMealOptionID (FK)
anything else needed here...
Any table obviously will also have whatever other fields you deem necessary for that table.

The answer to this question is here >
Database design for user settings
It's a edr diagram of how to store: N number of settings, that are associated with N Number of users, and each user can have a N number of settings associated with that individual user. So you could have one user with 5 settings and another user with 10 settings.
This is very flexible and I'll be using it in the future. I have swapped the entity user and replaced it with product.
What I want to know now is HOW DO YOU STORE SELECTED SETTINGS? These tables are only able to store and show user settings and available options/settings.
Any ideas?

Related

How to build complex relationships in CoreData correctly?

I am dealing with CoreData, for training, I decided to create a small application for recording user income and expenses. CoreData tutorials all contain To-Do-List examples, and I haven't found any good examples that would help me.
// MARK: - Grammar
// I want to apologize for grammatical errors in the text. Unfortunately,
// English is not my native language, so in some places I used a translator.
If something is not clear, I will definitely try to explain it again.
When I began to think over how I would implement the application, I assumed that the most convenient way would be to save all user operations and make calculations in the application in the right places. So far, abstract, since It seems to me that this has little to do with the question, if you need to be more precise, I can provide a complete idea.
So, I'm going to save the user model, which will have the following data:
User operations (Operation type) - all operations will be saved, each operation includes the category for which the operation was performed, as well as the amount in currency.
User-selected categories (Category Type) - Categories that will be used for expenses or income when adding an operation.
Wallets (Type Wallet) - User's wallets, Everything is simple, the name, and the balance on it.
Budget Units (BudgetUnit Type) - These are user budgets, contains a category, and a budget for it. For example: Products - 10.000 $
When I started building dependencies in CoreData, I got a little strange behavior.
That is, the user has a relationship on the same category model as the Budget Unit and Operation. Something tells me that it won't work that way.
I want the user categories to be independent, he selected them, and I'm going to display them on the main screen, and each operation will have its own category model
In the picture above, the category model is used 3 times, the same model.
This is roughly how I represent the data structure that I would like to see. Different models have their own category model, independently of the others.
I think it could be implemented using 3 different models with the same values, but it seems to me that this approach is considered wrong.
So how do you properly implement the data model so that everything works as expected? I would be grateful for any help!
--- EDIT ---
As a solution to the problem, I can create multiple entities as Category (Example bellow)
But I don't know if this is good practice
I looked into several other open source projects and saw a solution to the problem.
I hope this helps someone in the future.
There is no need to save the categories for the user, you can simply save the categories in the application by adding the IsSelected and ID parameter to them in order to change these parameters when you select a category, and immediately understand which ones you need to display.
For budgets and operations (transactions) , we only need to save the category ID to immediately display the correct one.
For example:
Thanks #JoakimDanielson and #Moose for helping. It gave me a different view of the subject.

DDD - Large aggregate and enforce invariant across aggregates

I'm kind of stuck at modeling this problem in the right way applying Domain Driven Design way. I want to model travelling group in a traveling agency.
We have concepts like passenger, group, and group member in one bounded context. This passenger is a large AR that holds all sorts of information, like name, job, address, bank account, religion, ANYTHING. But not all of them are necessary for all kinds of travels and their invariants differ based on the type of the trip. For example in travel type A, we don't need passengers' phone numbers. In travel type B we do. So when a person goes to create a group to go on travel type B, I will have an invariant on passenger AR to have a valid data for phone.
So basically there are two challenges here: How can I break this huge AR and how should I handle enforcing these conditional invariants? Is it OK if I enforce invariants on passenger AR inside handlers - application service- while creating group AR?
(Besides, the passenger AR and the group AR are in the same bounded context but they have the potential to be separated in the future).
I would say the constraint here should be not on passenger, but on the group.
At the end you may create passengers for different type of travels with or without phone numbers.
The actual constraint should be enforced like a passenger without a phone should not be added to that particular group as a group member.
Regarding the implementation side:
public void addPassengerToGroup(PassengerInformation passenger) {
//original code omitted
this.assertArgumentTrue(passenger.isPhoneInformationProvided(), "Passenger doesn't have contact information.");
this.groupMembers().add(passenger);
}
Somethink like this may solve your problem problem for constraint checks.
There is also some addition explanation for a similar situation:
https://softwareengineering.stackexchange.com/questions/319602/how-to-treat-validation-of-references-between-aggregates
This passenger is a large AR that holds all sorts of information, like name, job, address, bank account, religion, ANYTHING.
Well, to be honest, that sounds wrong as an aggregate. Consider why would you have this aggregate in the first place? What sort of business logic does this aggregate that involves the religion and bank account? or name? or address?
So, in short, this doesn't look like a Passenger aggregate. It looks more like a Customer record on a CRM without following DDD.
The first thing I would suggest is to consider your bounded contexts. I don't know your domain nor the specifics of your application, but most likely, you need bank account information for Finance reasons. So you'll have a Finance Bounded Context with Customers, their bank accounts, the invoices that you sent to them, and so on. You might also have a Bounded Context like Traveling or similar. Here, you might have a Passenger. A passenger could have a CustomerId and a TripId, plus other information, like ContactInformation and so on. You can also have Groups, with a list of Members and each Member could have a PassengerId and other information needed for the group management.
Obviously this is just an example from the limited information I have, but it seems to me, as I said, that a Customer becomes a Passenger when she signs up for a Trip. If the same Customer signs up for another trip, you'll create a new Passenger. There is no reason to reuse the same Passenger aggregate for multiple trips, because, as you said, even if it's the same person going to multiple Trips, the requirements for each are different, so trying to model a single Passenger that will fit all present and future types of Trips is creating an artificial coupling in my opinion.
Also, as I said previously, consider what information do you need on each aggregate. Even if across the whole application you know a lot of things from a single "person", it doesn't mean that you have to store them in a single place. That is the main point of DDD, in my opinion, finding where each piece of information belongs to and put it together with the business logic that needs it.

Core data max amount of entity

I am working on an app where I use core data.
I already have tried to do it with one entity but that didn't work.
But I now have like twenty entities and my question is: is there a limit to the number of entities or a number recommended?
Is there a better way to store that amount of data?
UPDATE:
What I am storing are grads from school but not the A,b,c,d,e,f but a number from 1 to 10. And each grad has is own weighing(amount of times a number count) like some grad count 2 time because the are more imported.
So i first thought to have an array with a string for the name of the subject and then to array one store's the grad the other the corresponding weighing.
Like this:
var subjects: [String,[Int],[Int]]
but this isn't possible and I don't even know how I should put this in core data and get it back properly.
Because I couldn't figure it out, I thought of just making a entity for each subject but there are a lot of them so there for this question.
There's no limit to the number of entities, but it's possible to go overboard and create more than you actually need. The recommended number is "as many as you need and no more", which obviously will vary a great deal depending on the nature of the data and how the app uses it. Whether there's a better way than your current approach is totally dependent on the fine details of exactly what you're doing, and so is impossible to answer without a far more detailed question.
You could setup a Subject entity that has one-to-many relationships to ordered sets of Grade and Weight, like so:
However, each grade apparently has a corresponding weight, so it would be more accurate to store each grade's weight in the Grade entity:
This still may not represent your real-world model.
If your subject is something general, like math or english, you could have more than one subject per grade, (e.g., algebra, geometry, trigonometry), or more than one level per subject (e.g., algebra 1, algebra 2) which may or may not have a different grade.
If your subject is very specific, your data may end up spread across unique one-to-one relationships, instead of one-to-many relationships.
You would also need to consider whether you can use ordered or unordered relationships, or whether an attribute exists that you can use to sort an entity.
You should consider these different facets of what you're trying to model (as well as the specific fetches you'd want to perform), before you try to design or implement the model, to allow you to efficiently represent this particular object graph.

MongoDB model design for meteorjs app

I'm more used to a relational database and am having a hard time thinking about how to design my database in mongoDB, and am even more unclear when taking into account some of the special considerations of database design for meteorjs, where I understand you often prefer separate collections over embedded documents/data in order to make better use of some of the benefits you get from collections.
Let's say I want to track students progress in high school. They need to complete certain required classes each school year in order to progress to the next year (freshman, sophomore, junior, senior), and they can also complete some electives. I need to track when the students complete each requirement or elective. And the requirements may change slightly from year to year, but I need to remember for example that Johnny completed all of the freshman requirements as they existed two years ago.
So I have:
Students
Requirements
Electives
Grades (frosh, etc.)
Years
Mostly, I'm trying to think about how to set up the requirements. In a relational DB, I'd have a table of requirements, with className, grade, and year, and a table of student_requirements, that tracks the students as they complete each requirement. But I'm thinking in MongoDB/meteorjs, I'd have a model for each grade/level that gets stored with a studentID and initially instantiates with false values for each requirement, like:
{
student: [studentID],
class: 'freshman'
year: 2014,
requirements: {
class1: false,
class2: false
}
}
and as the student completes a requirement, it updates like:
{
student: [studentID],
class: 'freshman'
year: 2014,
requirements: {
class1: false,
class2: [completionDateTime]
}
}
So in this way, each student will collect four Requirements documents, which are somewhat dictated by their initial instantiation values. And instead of the actual requirements for each grade/year living in the database, they would essentially live in the code itself.
Some of the actions I would like to be able to support are marking off requirements across a set of students at one time, and showing a grid of users/requirements to see who needs what.
Does this sound reasonable? Or is there a better way to approach this? I'm pretty early in this application and am hoping to avoid painting myself into a corner. Any help suggestion is appreciated. Thanks! :-)
Currently I'm thinking about my application data design too. I've read the examples in the MongoDB manual
look up MongoDB manual data model design - docs.mongodb.org/manual/core/data-model-design/
and here -> MongoDB manual one to one relationship - docs.mongodb.org/manual/tutorial/model-embedded-one-to-one-relationships-between-documents/
(sorry I can't post more than one link at the moment in an answer)
They say:
In general, use embedded data models when:
you have “contains” relationships between entities.
you have one-to-many relationships between entities. In these relationships the “many” or child documents always appear with or are viewed in the context of the “one” or parent documents.
The normalized approach uses a reference in a document, to another document. Just like in the Meteor.js book. They create a web app which shows posts, and each post has a set of comments. They use two collections, the posts and the comments. When adding a comment it's submitted together with the post_id.
So in your example you have a students collection. And each student has to fulfill requirements? And each student has his own requirements like a post has his own comments?
Then I would handle it like they did in the book. With two collections. I think that should be the normalized approach, not the embedded.
I'm a little confused myself, so maybe you can tell me, if my answer makes sense.
Maybe you can help me too? I'm trying to make a app that manages a flea market.
Users of the app create events.
The creator of the event invites users to be cashiers for that event.
Users create lists of stuff they want to sell. Max. number of lists/sellers per event. Max. number of position on a list (25/50).
Cashiers type in the positions of those lists at the event, to track what is sold.
Event creators make billings for the sold stuff of each list, to hand out the money afterwards.
I'm confused how to set up the data design. I need Events and Lists. Do I use the normalized approach, or the embedded one?
Edit:
After reading percona.com/blog/2013/08/01/schema-design-in-mongodb-vs-schema-design-in-mysql/ I found following advice:
If you read people information 99% of the time, having 2 separate collections can be a good solution: it avoids keeping in memory data is almost never used (passport information) and when you need to have all information for a given person, it may be acceptable to do the join in the application.
Same thing if you want to display the name of people on one screen and the passport information on another screen.
But if you want to display all information for a given person, storing everything in the same collection (with embedding or with a flat structure) is likely to be the best solution

Am i violating any NF RULE on my database design?

Good day!
I am a newbie on creating database... I need to create a db for my recruitment web application.
My database schema is as follows:
NOTE: I included the applicant_id on other tables... e.g. exam, interview, exam type.
Am i violating any normalization rule? If i do, what do you recommend to improve my design? Thank you
Overall looks good. A few minor points to consider:
Interviewer is also a person. You will need to use program logic to prevent different / misspellings.
The longest real life email address I've seen was 62 characters.
In exam you use the reserved word date for a column name
(subjective) I would rename applicant_date to applied_at
I don't see a postal / zip code for the applicant
All result columns are VARCHAR(4). If they use the same values, can they be normalized?
Birthdate is better to store then age. You don't want to schedule someone for an interview on their birthdate (or if you're cruel by nature, you do want that :) ). Age can be derived from it and will also be correct at all times.
EDIT:
Given that result is PASS or FAIL, simply declare the field a boolean and name it 'passed'. A lot faster.
One area where I could see a potential problem is the Interviewer being integrated in interview. Also I would like to point at the source channel in applicant, which could potentially get blobbed (depending of what you're going to store in there).
You don't seem to be violating any normalization rules upon first glance. It's not clear from your schema design, however, that the applicant_id is a referencing the applicant table. Make sure you declare it as a foreign key that references the applicant table when actually implementing the scehma.
Not to make any assumptions on your data, but can the result of a screening be stored in 4 characters?
Age and gender are generally illegal questions to ask in interviews so you may not want to record such things. You might want a separate interviewer table. You also might want a separate table that stores qualifications so you can search for people you have interviewed with C# knowledge when the next opening comes up. I'd probably do something like a Qualifications table that is the lookup for quals you want to add to the applicant qualfications table. Then you'd need the qualification id, applicantId, years, skill level in the Applicant Qualification table.
I notice results is a varchar 4 field, I assume you are planning to put Pass/fail in it. I would consider having a numeric score as well. The guy who got 80% of the questions right passed but the guy who got 100% of them right might be the better candidate. In fact for interviews I might have interview questions and results tables. Then you can record the score and any comments about each question which can help later in evaluation of a lot of candidates. We did this manually in paper spreadsheets once when we were interviewing several hundred people (we had over a hundred openings at the time and this was way before personal computers) and found it most helpful to be able to compare answers to questions. It's hard to remember 200 people you interviewed and who said what. It might help later when you have a new opening to find the people who were strong onthe questions most pertinent to the new job who might not have been given a job at the time of the interview(5 excellent candidates, 1 job for instance).
I might also consider a field to mark if the candidate is unaccepatble for ever hiring for some reason. Such as he committed a felony or he lied on the resume and you caught him or he was just totally clueless in the interview. This can make it easy to prevent this person from being considered repeatedly.
I think that your DB structure has a lot of limitation for future usage. For example you can even have a description of the exam because this stable store the score and exam date. It may by that this kind of information are already stored in another system and you have to design only the result container. But even then the exam, screen and interview are just a form of test, that why the information about should be stored in one table and distinguished by some type id. If you decide to this approach you have to create another table to store the information about result
So the definition of that should look more like this:
TEST
TEST_ID
TEST_TYPE_ID ref TEST_TYPE - Table that define the test type
TEST_REQUIRED_SCORE - The value of the score that need to be reach to pass the exam.
... - Many others properties of TEST like duration, expire date, active inactive etc.
APPLICANT_RESULTS
APPLICANT_ID ref APPLICANT
TEST_ID = ref TEST
TESTS_DATE - The day of exam
TEST_START - The time when the test has started
TEST_FINISH - The time when the test has ended
APPLICANT_RESULT - The applicant result of taken test.
This kind of structure is more flexible and give the easy way to specify the requirements between the test in table like this
TEST_REQUIREMENTS - Table that specify the test hierarchy and limitation
TEST_ID ref TEST
REQUIRED_TEST ref TEST
ORDER - the order of exams
Another scenario is that in the future your employer will want to switch to an e-exam system. In that case only think what you will need are:
Create table that will store the question definition (one question can be used in exam, screen or interview)
Crate table that will store the question answers.
Create table that will store the information about the test question.
Create table for storing the answer for each question given from applicant.
A trigger that will update the over all score of test.