I have 3 entities - User, UserGroup and Group. User and UserGroup has many-to-many relationship and Group and UserGroup has one-to-many relationship. So on EF side, User object has a UserGroup collection and UserGroup has a Group property. Group entity has a property called Level, which is a number giving the group sort of a rank
I want to retrieve all users, along with the Group with the max Level. How do I do that?
Using tuples you could do something like:
Users.Select(u => (u, u.UserGroups.Select(ug => (ug.Group, ug.Group.Level))
.OrderByDescending(t => t.Item2).FirstOrDefault()?.Item1)))
Assuming I've understood your description (posting code would be better).
Related
Suppose I have following 4 collections:
1- posts
2- companies
3- groups
4- users
Bellow is my current structure in post:
and their relation is:
A company has an owner and many other members (user collection).
A group has many members (users).
A user has many posts.
A group has many posts that published by one of its members.
A company has many posts that published by its owner or members.
Now i have a problem on storing relation of users, company, and group with posts collection.
Bellow is my current structure:
I have decided to have a field postable inside my post document, and has a type field that will be 'user', or 'group', or 'company', and two other fields name, and id that will be company/group id and company/group name in cases that post is belonged to company or group but not user means type="group" || type="company".
Now how i can handle this to map id as FK of group and company collection (one field FK of two collection) ?
Is it the right structure ?
What you have here is a polymorphic association. In relational databases, it is commonly implemented with two fields, postable_id and postable_type. The type column defines which table to query and id column determines the record.
You can do the same in mongodb (in fact, that is what you came up with, minus the naming convention). But mongodb has a special field type precisely for this type of situations: DBRef. Basically, it's an upgraded id field. It carries not only the id, but also collection name (and database name).
how i can handle this to map id as FK of group and company collection (one field FK of two collection)?
Considering that mongodb doesn't have joins and you have to load all references manually, I don't see how this is any different from a regular FK field. Just the collection name is stored in the type field now, instead of being hardcoded.
I am using EF 6 Code-First, table per type, and I have two concrete classes Group and User. Group has a navigation property Members which contains a collection of User. I have mapped this many-to-many relationship in EF using Fluent syntax:
modelBuilder.Entity<Group>
.HasMany<User>(g => g.Members)
.WithMany(u => u.Groups);
I would like to be able to say when a member has joined a group so that I can query for, say, the newest member(s). I am not sure of how this is best accomplished within the framework.
I see the following options:
Create and use an audit table (ie GroupMembershipAudit consisting of Group, User, join/unjoin, and DateTime
Add a column to the autogenerated many-to-many table between User and Group
Is there anything within EF to facilitate this sort of storage of many-to-many historical info like this / append columns to the many-to-many relationship?
Add a column to the autogenerated many-to-many table between User and
Group
That is not possible - auto-generated junction tables can contain only keys (that is called Pure Join Table). According to Working with Many-to-Many Data Relationships article: If the join table contains fields that are not keys, the table is not a PJT and therefore Entity Framework cannot create a direct-navigation (many-to-many) association between the tables. (Join tables with non-key fields are also known as join tables with payload.)
Create and use an audit table (ie GroupMembershipAudit consisting of
Group, User, join/unjoin, and DateTime
Actually you should create GroupMembershipAudit entity. With Code First table will be generated, you don't need to create it manually.
I am a beginner to using JPA 2.0 and databases in general and I was just confused about a few concepts.
So I have a total of 3 tables. One is the UserTable, which contains all the information about my user. It has a primary key field called user_Id. My other two tables are ExercisesTable and FoodIntakeTable, and they each have a foreign key field called user_Id to reference the user_Id in my UserTable. I want a one-to-many relationship from my user_Id table to each of the two tables so I can find pull out exercise information or food information for a user.
Pretty much like this:
FoodIntakeTable <-> UserTable <-> ExercisesTable
I need a bidirectional mapping from UserTable to FoodIntakeTable and also a bidirectional mapping from UserTable to ExercisesTable from the field user_Id.
The problem is, when I try to write my code like this in my Usertable class:
#OneToMany(mappedBy="ExercisesTable.userId")
#OneToMany(mappedBy="FoodIntakeTable.userId")
public long userId;
It's illegal because I can't have two #OneToMany annotations on the same field. I think it's supposed to be legal in a normal relational database and I'm just confused about how you translate this into JPA. I'm very new to the whole concept of databases and entities in general, so any help would be appreciated.
In JPA you can directly reference entity objects instead of the ids that they are mapped by. Try something like this:
You should have an entity type for each of your tables, say Exercise for ExercisesTable, FoodIntake for FoodIntakeTable, and User for your UserTable.
Then your User entity is the owning side of the relationships, having one field per relationship like this:
#OneToMany(mappedBy=...)
private List<Exercise> exercises;
#OneToMany(mappedBy=...)
private List<FoodIntake> foodIntakes;
I have 4 tables/entities which fall into two groups, alerts and recipients. Either entity from a group can map to either entity of the other group (an Alert can have many Recipients and RecipientGroups and so on).
Tables:
Alerts
AlertGroups (1 to many relationship with alerts)
Recipients
RecipientGroups (many to many relationship with recipients)
Instead of making 4 jointables (AlertRecipients, AlertRecipientGroups, etc.) I want to make one join table with 4 columns, each column being a nullable FK for one of my entity types.
I've made the table in SQL, and set up my context using Fluent API like so:
modelBuilder.Entity<AlertGroup>()
.HasMany(ag => ag.RecipientGroups)
.WithMany(rg => rg.AlertGroups)
.Map(m => m.ToTable("AlertRecipients")
.MapLeftKey("AlertGroupID")
.MapRightKey("RecipientGroupID"));
modelBuilder.Entity<AlertGroup>()
.HasMany(ag => ag.Recipients)
.WithMany(rg => rg.AlertGroups)
.Map(m => m.ToTable("AlertRecipients")
.MapLeftKey("AlertGroupID")
.MapRightKey("RecipientID"));
But I get this error:
Schema specified is not valid. Errors:
(251,6) : error 0019: The EntitySet 'AlertGroupRecipient' with schema
'dbo' and table 'AlertRecipients' was already defined. Each EntitySet
must refer to a unique schema and table.
Is there a workaround to do what I'm trying to do?
EF is not able to do that this way. With EF you need separate join table for every many-to-many relationship (because that is the way how you should do that). If you want to do that your way you cannot use many-to-many association in the mapping. You must instead "upgrade" your AlertRecipients to the real entity (another class in your model) and handle everything like one-to-many association.
I have an entity that has a relationship with another entity. I am able to search on columns that are in the main entity, and include columns from the relationship entity. But I need to be able to filter the list (search) on columns that are not in the relationship entity.
for example
the Invoice Entity contains a customerId property, and is related to the Customer Entity which contains the customerName property
I need to be able to search / filter the grid by customerName.
I am new to entity framework, please help.
thanks
Carl
Your relation is 1->1. In these cases I usually return a custom class to the grid that has all the columns I need, including joins with other tables.
So basically what you need is to create a custom linq query with your resultset.
The mais query should follow this example:
var q = from i in ctx.Invoices
join c in ctx.Customers on i.CustomerID equals c.CustomerID
select new{InvoiceID=i.InvoiceID, InvoiceDate=i.Date, CustomerName=c.Name};
Now, assuming we receive a CustomerName variable with the string to filter by c.Name we could do:
if(!string.IsNullOrEmpty(CustomerName))
{
q = q.where(c => c.Name.ToLower().Contains(CustomerName.ToLower()));
}
Notice that I'm performing a ToLower() operation and a Contains, this will beahave as a LIKE ingnoring case sensitivity and searching for the string anywhere in the Customer Name.
At the end you'll return the q.ToList() serialized for the jqGrid...