Relate two entities via a third one - spring

I am trying to figure it out how to relate two entities using another one they both have in common. My model is the following:
A Customer has a list of Codes
A Promotion has a list of Codes
A Code has a list of Customers and a list of Promotions
I would like to add to the Promotion Entity a list of Customers. This list would include all customers who at least have the same codes as in the promotion (can have more). Ideally I would like to model this a field but I am not sure if this is possible. I have found no information.
Can it be done?
Thanks,

You can define
Customer Entity.
Code entity which has #ManyToMany relationship with Customer. ( This is required if customer can have code even when there is no promotion.)
Promotion Entity which has #ManyToMany relationship with Customer
and #ManyToMany with Code.

At the end I ended up doing the following
public Set<Customers> getCustomers(){
Set<Customers> customers = null;
for (Code c : codes)
if(customers == null)
customers = c.getCustomers();
else
customers.retainAll(c.getCustomers());
return customers;
}
I do a Eager retrieve for the Codes, and in the codes an Eager retrieve for the Customers. So far is performing well, but I would prefer this to be all calculated in the DBMS and not on the controller side. Still have not find a nice way to to it.

Related

Laravel models, database and pivot tables question

Hello I am working with Laravel,
I have to create two simple models, let's say Stores and Books.
Stores can have one or multiple Books and Books can belong to many Stores.
Of course I will use a many to many relationship, with a pivot table.
Books the can have different prices depending the store.
I think a separate table can only complicate things, in my mind the pivot table associating books and stores should have a price column, but pivot tables only contains store_id and book_id.
Should I create a book_prices and associate it with books and to stores? What is the best approach?
You are free and able to set other attributes on your pivot table. You can read more about it in the docs.
https://laravel.com/docs/9.x/eloquent-relationships#retrieving-intermediate-table-columns
You have to define the relationship accordingly, the following should clarify how this works. In this example you use the many-to-many relationship and add the price column to every retrieved pivot model.
public function books()
{
return $this->belongsToMany(Book::class)
->withPivot('price')
}
For example, you are able to access the pivot column in a loop like this
foreach ($shop->books as $book)
{
echo $book->pivot->price;
}
You can define additional columns for your pivot table in the migration for the pivot table, and then when defining the relationship use withPivot to define the additional columns so they come through in the model:
return $this->belongsToMany(Book::class)->withPivot('price');
(Adapted from the Laravel documentation, see https://laravel.com/docs/9.x/eloquent-relationships#retrieving-intermediate-table-columns)
Depends on the complexity of your case, but yes, you have two options for it. Let's say that the pivot table is called as book_store:
Directly adds price column to book_store. This is obviously the simpler option. The drawbacks are:
The history of the price changes isn't logged. You'll have to create another table for logging if you want to keep this history information.
Changes made to price will directly change the price of the related book_store record. Meaning that a price is being updated "live" e.g users cannot update the price now but "publish" it some time later just like this example in the doc.
Create a new, different table to store the price. This may seems relatively more complex, but it may also be more future-proof.
Basically, you get 2 things that you miss in the first option above.
Don't think too much about book_store being a pivot table. One way to see it is like this: book_store IS a pivot table from books and stores tables viewpoints, but it's also just a normal SQL table which could relate to any other tables using any kind of relationships.
If you want to implement this, make sure to create a primary-key in the book_store table.
Alast, it all depends on what you need. Feel free to ask if you need more insight about this. I hope this helps.

Inverse of belongsToMany

I got two Models:
Order
Invoice
Each Order can have many Invoices - and an Invoice can belong to many Orders.
So I can search for an Order and check: "Hey, which Invoices have been created for this Order?"
The other way round each Invoice can belong to multiple Orders, because maybe a customer ordered two products on the same day and so it would be great he'd only get one Invoice, which includes both orders.
So this is how I did this:
Invoice
public function orders()
{
return $this->belongsToMany(Order::class);
}
Order
public function invoices()
{
return $this->belongsToMany(Invoice::class, 'invoice_order');
}
This does work - but it does not seem right to change the table to the intermediate table invoice_order here. Do you have any thoughts on this? :-)
Thanks in advance for your thoughts :-)
Seperating the relation into a seperate pivot table is the commonly used method in laravel (and in most other frameworks) for many to many relationships.
It's easy to maintain, easy to get related models using many to many relationship, and if someone else needs to work on it in the future, they'll probably have used it in the past as well so wouldn't end up burning their heads.
The other method you could use is to create a json column on one of the tables (you can create on both tables as well if you want, but that's just extra overhead). Then you can store the ids of the related models in this json column. You can then join the tables using the json related commands provided by your database. Eloquent does not support relationships on json, but you can use this package staudenmeir/eloquent-json-relations to build relationships on json fields.
So overall, I'd suggest keeping a pivot table like the standard way, but if that just won't do, then you can try the json column method

Runtime join in lightswitch

I have a generic group members table with a GUID for a "group type" and a GUID for "referenced object". An example would be if I have a table of customers(each having a GUID) I can group them under "already paid" by creating a group GUID and in my "Group members table" referencing every customer by their respective GUID. This allows for any type of group to be added to the model as we expand(without adding extra tables).
Here is the problem. I have created a subquery in an entity in order to filter the universal group members table for a certain group and what "items" are and are not in that group; like so:
partial void ElementsNotMemberOfGroup_PreprocessQuery(int? UniversalGroupTypeIDParameter, int? UniversalGroupsIDParameter, ref IQueryable<UniversalGroupMember> query)
{
query = query.Where(x => x.UniversalGroup.UniversalGroupType.UniversalGroupTypeID == UniversalGroupTypeIDParameter);
query = query.Where(x => x.UniversalGroup.UniversalGroupsID != UniversalGroupsIDParameter);
}
This returns the GUIDs for the referenced object in the group, but for a user that's useless. I need to join this table and my customers table at runtime on the GUID so I can extract the customer info and display it.
Any Ideas?
LightSwitch wasn't really created with this kind of scenario in mind. LightSwitch makes things very easy for you when you create relationships between tables that are, well, "related". When you do this, you never need manual joins between entities.
While it's possible to do something similar to what you're describing (see the link below), it's a lot more work to achieve it, and in my opinion it isn't really worth the extra trouble. Not only that, but as you're discovering, it complicates even the most simple operations.
In essence, you're working against LightSwitch, instead of with it. My advice to you would be that if you really must do this type of manual optimization, then LightSwitch may not be the best product for you to use.
Beth Massi has a blog article, Using Different Edit Screens Based on Record Types (Table Inheritance), which isn't exactly what you're doing, but it may give you some ideas if you decide to still use LightSwitch for your project.

Linq doubts with DB context

Hi I have a question that is braking my mind for some days.
I have my SQL server Database and my C# application.
In the DB I have differemt tables, let me show you a simple ex
Tables:
Person
Relationship
City
Business Rules:
The person are from a City, so the person has IdCity
A person has a relationship with other person, and about that relationship you need to save the starting date.
In other projects I already did something like that, but in this proyect this is not working for me.
When I retrieved with LinQ the information about the person, the city is not coming, and an error appears when I try "person.city.description", for ex.
I try using Include("City") in the linq query, but it didn't work. Besides that, I don't know how to manage the circular reference to the person to person relationship.
One important thing, that I think that can be the problem, is that I rename all the tables from the DataModel, for example, the table in database is called Prd_City, so I change the Name and the Entity Set Name for City in c# project. So in the included I have to use the real table name, in other case the query fail, but if I use the real name nothing happens.
using (var context = new MyContext())
{
List<Person> oPeople = (from p in context.Person.Include("Prd_City")
select p).ToList();
return oPeople ;
}
Any help will be welcome.
Thanks!
"It didn't work" is never a good description of your problem. But from the rest of your question I can infer that Person has a navigation property named "Prd_City", while you expected it to be "City". The thing is: you renamed the entities, but not the navigation properties in the entities.
My advice (for what it's worth): it seems that your work database-first. If you can, change to code-first and manually map the POCO classes to their table names, and properties to their database columns. It may be a considerable amount of work (depending on the size of your data model), but after that you will never run the risk of EF "un-renaming" your entities. Besides, the DbContext API is easier to use than ObjectContext. Currently, it's the preferred EF API.

Automatically inversing relations in Doctrine2.x

In Doctrine 1.2, you used to be able to automatically define a collection on the opposite side of a relation by defining it only on the owning side. The other side needn't know about the class that was relating to it.
Is it possible to do this in Doctrine 2.x without having to create a variable and mapping on the owned side?
While it probably is allowed, I woudn't do that. Take this example:
1) Category has Many products. So you fetch a page with most-sold products and show its Category name; you must have that relation on Products side.
2) Let's say that Category can be deleted only if there are no products. So you would have a method:
public function isDeletable()
{
return count($this->getProducts())==0 ;
}
I am sure better examples could be made, I just made it quick&dirty. My suggestion would be to always put both sides because you will never know when it will become handy, and it also makes consistency in your entities.

Resources