I have two junction/bridge tables, DailyLogEmployees and DailyLogVendors to handle a many to many relationship:
public class DailyLog:ActiveEntity
{
public int Id {get;set;}
[ForeignKey("EmployeeId")]
public ICollection<Employee> Employees { get; set; }
[ForeignKey("VendorId")]
public ICollection<Vendor> Vendors { get; set; }
}
and defined in the model as such
modelBuilder.Entity<DailyLog>().HasMany(d => d.Employees).WithMany().Map(m =>
{ m.MapLeftKey("DailyLogId");
m.MapRightKey("EmployeeId");
m.ToTable("DailyLogEmployees");
});
modelBuilder.Entity<DailyLog>().HasMany(d => d.Vendors).WithMany().Map(m =>
{ m.MapLeftKey("DailyLogId");
m.MapRightKey("VendorId");
m.ToTable(
"DailyLogVendors");
});
The items are created in the metadata, however when I instantiate a new DailyLog, neither Employees or Vendors are present.
Breeze is version 1.3.6 am I doing something stupid, I don't want any navigation on the other side, Employees or Vendors just on the DailyLog any help or insight is appreciated.
Breeze does not YET support many-many relations. For the time being you can expose these as two 1-many relations... and please add your vote to our User-Voice on this topic.
Related
I have the following models
public class Student
{
public int Id {get; set; }
public string Name {get; set; }
public ICollection<StudentToCourse> StudentToCourse {get; set; }
}
public class StudentToCourse
{
public int StudentId{get; set; }
public Student Student {get; set; }
public int CourseId{get; set; }
public Course Course {get; set; }
}
public class Course
{
public int Id {get; set; }
public string Name {get; set; }
public ICollection<StudentToCourse> StudentToCourse {get; set; }
}
I want to get a list of all COURSE per student ID, how do I go about doing that?
Short answer: SELECT and match on the Id values. Or programatically -
foreach(Student s in yourstudentList)
{
foreach(StudentToCourse stc in s.StudentToCourse)
{
if(stc.StudentId = s.Id)
//this is one you want, do something with it
}
}
Better answer:
First let's look at your model...
Imagine the underlying database structure.
Your middle table is known as a lookup.
You don't really need the entire Student, nor the entire Course object in it.
Also, your Course object does not need to know about either of the other objects.
If you can imagine three tables in your database you can see how you would logically connect a Student to a Course across the three tables.
Your model is still incomplete though. Within your application you still need a container, in this case a List courseIds. In this way your Student doesn't need to care about all the entries in the Student/Course lookup table, just the ones applicable to the particular Student. And you have an easily accessible object to pull data from, or send updates to, the database.
On initial population of the courseIds collection you would do a
SELECT FROM StudentToCourse where StudentId = x
You can then JOIN on your Course table to pull values such as the Course name.
If you find you need to do a lot of those look ups you may cache your Course list and lower your database traffic at the cost of some ram.
Each time you make a new student you would want to populate their list of course Ids and when committing the student to the database you would save your look up table.
This keeps your objects as lightweight as possible while maintaining their relationships.
There are various ways to write the SELECT statement in your dev environment, search them out and find one you like (or that matches your company's current practices) and get used to consistently using the same one. It will keep your code more readable and manageable.
I am a beginner and learning fluent API from tutorials. I read the some of the already given SO solution about 1-0, 1-* but I could not understand them properly. I simply want to use fluent API to set up One to One and One to Zero Relationship provided no convention followed.
House and Room (terrible example)
Requirement:
1. One House can have zero room or ONE room MAX.
2. One Room must be inside a house.
3. If a room is deleted House SHOULD NOT Get Deleted
4. If a House is getting deleted and there is a room then
User should first delete the room then only House should be allowed to be deleted.
public class House
{
public int HouseId { get; set; }
public string HouseName { get; set; }
public virtual Room Room { get; set; }
}
public class Room
{
public int RoomId { get; set; }
public string RoomName { get; set; }
public int HouseId { get; set; }
public virtual House House { get; set; }
}
So, Room cannot exist w/o a House but a House can exist w/o a room. Also, in case if a House has room, it can only have one.
dBModelBuilder.Entity<House>()
.HasOptional(f => f.Room)
.WithRequired(s => s.House);
I saw some solution but they are telling to set the PK and FK same. But I don't want to do that. Is there a way to achieve what I want w/o setting PK and FK same. I DO NOT want the HouseID to be PK of my Room class. Also in my case principal is House and Dependent is Room. Do I need to add soemthing like "Optional Dependent" or "Optional Principal". Can some one please guide me I am a beginner.
Also, Do I need go remove navigation property from any of my MODELS? Is that extraneous?
How to tell EF to use HouseId of Room class as FK.
Also in my case principal is House and Dependent is Room
Then you are on the right track with
modelBuilder.Entity<House>()
.HasOptional(f => f.Room)
.WithRequired(s => s.House)
because in EF one-to-one relationship the required side is always the principal. You need to specify the principal/dependent only when both sides are required or both sides are optional.
The problem is your requirement of using different FK in the dependent entity than the PK, which is the default EF model for such relationship (so called Shared Primary Key Association), and is supported well. From the other side, one-to-one FK association is supported, but with some limitations. More specifically, explcit FK property like HouseId in your Room is not supported - there is no HasForeignKey fluent method for this type of configuration, and it's by purpose. I can't say why, but it's a fact. If you try playing with [ForeignKey] attribute, you'll get quite unexpected results, so don't do that.
Remove that property:
public class Room
{
public int RoomId { get; set; }
public string RoomName { get; set; }
public virtual House House { get; set; }
}
and use Map fluent API with MapKey to specify the FK column name:
modelBuilder.Entity<House>()
.HasOptional(f => f.Room)
.WithRequired(s => s.House)
.Map(c => c.MapKey("HouseId"));
This will give you the desired database table design (although there is no way to constrain HouseId column to be unique, except manually editing the migration).
Can I use something like:
public virtual Dictionary<User, double> Tenants { get; set; }
where what I want is a dictionary of Tenants in the way of:
User1, 25%
User2, 30%
User3, 45%
which says how much each person own from a House model (the virtual property above is in the House model).
How could I do this and is the current way of doing it correct?
As you mentioned entity-framework in your question tags then i can suppose what you try to map some relations to virtual IDictionary<T,T> in your data access class. But EF supports only things like this virtual IColletions<T>
But if this just a field for your view model which is separated from data access logic then it can be anything you want.
But maybe it will be bettor if you create something like
public Dictionary<int, CustomUserObjectWithShare> Tenants {get; set;}
public class CustomUserObjectWithShare
{
public User User { get; set;}
public Decimal Share { get; set; }
}
I am new to EF6 and fluent API, but I really tried all the possibilities before trying to bother you here but I am kind of stuck now.
I have the following model:
public class Event
{
public int Id { get; set; }
[Required]
public string Label { get; set; }
}
public class Address
{
public int Id { get; set; }
[Required]
public String City { get; set; }
}
Here's what I am trying to do:
The event should have a required field Address
The address can be used in an event or in another class (let's call it Person for example). Therefore, it shouldn't be directly be bound to the Event class
When deleting an Event (or Person), I want to cascade and delete the linked Address
I tried many possibilities in Fluent API by looking at the documentations and searching on the net. Despite that, I kept having various issues: conflicting multiplicities, inconsistent model or not being able to cascade on delete.
Could someone please help? I am really stuck! :)
Thank you!
!!!UPDATE!!!
As requested, here's the best solution I could find:
public class Event
{
public int Id { get; set; }
[Required]
public string Label { get; set; }
[Required]
public virtual Address.Address Address { get; set; }
}
public class Address
{
public int Id { get; set; }
[Required]
public String City { get; set; }
}
And the fluent code as follows:
modelBuilder.Entity<Event>()
.HasRequired(e => e.Address)
.WithOptional()
.Map(e => e.MapKey("AddressId"))
.WillCascadeOnDelete(true);
This implementation adds a foreign key in the Event table to the Address table. However, the cascade on delete will work in the following direction: deleting the Address will delete the Event. Unfortunately, I am trying to accomplish the opposite: I want the Address to be deleted only when the Event is!
Thank you again :)
Your requirements are fighting each other.
Cascade delete is from principal to dependent, so when an Address should be deleted when an Event is, the Event must be the principal (the entity to which a foreign refers).
If more than one class must have an Address, the other classes should refer to Address, which makes Address the principal.
There is an alternative. Address could have two foreign keys, to Person and to Event. But this is not very appealing, because the keys must both be nullable and there is no database constraint to enforce that they are mutually exclusive.
Another alternative is to make Address a complex type, so both the Event and the Person tables will have all address columns. Of course this is not well normalized, and you can't handle Addresses as separate entities, but at least there is no cascade issue, because an address is part of the Event record.
I think your best option is to have several classes refer to Address and write logic to delete orphan addresses.
While researching whether or not ASP.NET MVC is suited for my next website, I've come across an annoying issue.
I have followed ASP.NET MVC since version 2, and it's gotten better. For instance, it's now fairly easy to get going with migrations in the entity framework with code first, which used to be a hassle.
This means that I now can get running with a database migrations and code first within half an hour (as I usually don't remember the steps involved, I have to follow a guide I wrote).
Now, fairly early on I always get a many-to-many relationship between entities (e.g. tags and posts) in my database, and what I've found is that getting this relationship exposed via MVC framework is surprisingly complicated! Example from asp.net Example from mikesdotnetting
It involves special methods to retrieve the relationship's data that is not an inherent part of the framework.
Is there really no better/easier way of treating the many-to-many relationship?
You should add a virtual key word to the Many port
public class Post
{
[Key]
public int ID { get; set; }
public string Title { get; set; }
public virtual ICollection<Tag> Tags {get;set;}
}
public class Tag
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Post> Posts {get;set;}
}