EF Code First mapping for collection - entity-framework

I'm using EF 4.1 RC Code first. I have a many to many relation working with a composite PK in the junction table Friends. We explicitly need a separate Friends class (don't ask) which represents our junction table. Our goal is to be able to control the delete process from the User entity. Please read this before reading the rest: http://mocella.blogspot.com/2010/01/entity-framework-v4-object-graph.html. So, we managed to create our composite PK but this broke our mapping for the collection. The question is how to map FriendsCol?
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public virtual ICollecion<Friends> FriendsCol { get; set; }
}
public class Friends
{
public int User1Id { get; set; }
public int User2Id { get; set; }
public User User1 { get; set; }
public User User2 { get; set; }
}
Have a composite key mapping
public class FriendsMap : EntityTypeConfiguration<Friends>
{
HasKey(m => new { m.userId1 , m.userId2 });
//this.HasRequired(x => x.User1)
//.WithMany()
//.HasForeignKey(x => x.User1Id)
//.WillCascadeOnDelete(false);
//this.HasRequired(x => x.User2)
// .WithMany()
// .HasForeignKey(x => x.User2Id)
// .WillCascadeOnDelete(false);
}
public class UserMap : EntityTypeConfiguration<UserNew>
{
public UserMap()
{
ToTable("users");
Property(user => user.Name).HasColumnName("name");
// HasMany<Friends>(user => user.FriendsCol).WithMany();
}
}

What about this:
public class FriendsMap : EntityTypeConfiguration<Friends>
{
HasKey(m => new { m.userId1 , m.userId2 });
this.HasRequired(x => x.User1)
.WithMany()
.HasForeignKey(x => x.User1Id)
.WillCascadeOnDelete(false);
this.HasRequired(x => x.User2)
.WithMany(u => u.FriendsCol)
.HasForeignKey(x => x.User2Id)
.WillCascadeOnDelete(false);
}
public class UserMap : EntityTypeConfiguration<UserNew>
{
public UserMap()
{
ToTable("users");
Property(user => user.Name).HasColumnName("name");
}
}
Edit:
I just made very simple example and it works without any problem:
class Program
{
static void Main(string[] args)
{
using (var context = new Context())
{
context.Database.Delete();
context.Database.CreateIfNotExists();
var u1 = new User() { Name = "A" };
var u2 = new User() { Name = "B" };
var u3 = new User() { Name = "C" };
var f1 = new Friends() { User1 = u1, User2 = u2};
var f2 = new Friends() { User1 = u1, User2 = u3 };
context.Friends.Add(f1);
context.Friends.Add(f2);
context.SaveChanges();
}
}
}
public class User
{
public int UserId { get; set; }
public string Name { get; set; }
public virtual ICollection<Friends> FriendsCol { get; set; }
}
public class Friends
{
public int User1Id { get; set; }
public int User2Id { get; set; }
public User User1 { get; set; }
public User User2 { get; set; }
}
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Friends> Friends { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Friends>()
.HasKey(m => new { m.User1Id, m.User2Id });
modelBuilder.Entity<Friends>()
.HasRequired(x => x.User1)
.WithMany()
.HasForeignKey(x => x.User1Id)
.WillCascadeOnDelete(false);
modelBuilder.Entity<Friends>()
.HasRequired(x => x.User2)
.WithMany(u => u.FriendsCol)
.HasForeignKey(x => x.User2Id)
.WillCascadeOnDelete(false);
}
}

Ok, here is what really should happen:
class Program
{
static void Main(string[] args)
{
int id1;
int id2;
using (var context = new Context())
{
context.Database.Delete();
context.Database.CreateIfNotExists();
var u1 = new User() { Name = "A" };
var u2 = new User() { Name = "B" };
var u3 = new User() { Name = "C" };
var f1 = new Friends() { User1 = u1, User2 = u2 };
var f2 = new Friends() { User1 = u1, User2 = u3 };
u1.FriendsCol.Add(f1);
u1.FriendsCol.Add(f2);
context.SaveChanges();
id1 = u1.Id;
id2 = u2.Id;
}
using (var context = new Context())
{
var u1 = context.Users.Find(id1);
var friendsToRemove = u1.FriendsCol.Where(f => f.User2.Id == id2).ToList();
foreach (var friend in friendsToRemove)
{
u1.FriendsCol.Remove(friend);
}
context.SaveChanges();
}
}
}
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Friends> FriendsCol { get; set; }
public User()
{
FriendsCol = new List<Friends>();
}
}
public class Friends
{
public int User1Id { get; set; }
public int User2Id { get; set; }
public User User1 { get; set; }
public User User2 { get; set; }
}
public class Context : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Friends> Friends { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Friends>()
.HasKey(m => new { m.User1Id, m.User2Id });
modelBuilder.Entity<Friends>()
.HasRequired(x => x.User1)
.WithMany()
.HasForeignKey(x => x.User1Id);
modelBuilder.Entity<Friends>()
.HasRequired(x => x.User2)
.WithMany(u => u.FriendsCol)
.HasForeignKey(x => x.User2Id);
}
}

Here is another fail to delete related entities. And this is the error: *A relationship from the 'Order_Lines' AssociationSet is in the 'Deleted' state. Given multiplicity constraints, a corresponding 'Order_Lines_Target' must also in the 'Deleted' state.*
class Program
{
static void Main(string[] args)
{
int orderid1;
int Lineid2;
using (var context = new Context())
{
var u1 = new Order() { Name = "A" };
var l1 = new OrderLine() { Name = "L1" };
var l2 = new OrderLine() { Name = "L2" };
u1.Lines.Add(l1);
u1.Lines.Add(l2);
context.Orders.Add(u1);
context.SaveChanges();
Orderid1 = u1.Id;
Lineid2 = l2.Id;
}
using (var context = new Context())
{
var u1 = context.Orders.Find(Orderid1);
foreach (var item in u1.Lines)
{
if (item.Id == Lineid2)
{
u1.Lines.Remove(item);
break;
}
}
context.SaveChanges();
}
}
}
public class OrderLine
{
public int Id { get; set; }
public string Name { get; set; }
public Order Order { get; set; }
}
public class Order
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<OrderLine> Lines { get; set; }
public Order()
{
Lines = new List<OrderLine>();
}
}
public class Context : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<OrderLine> OrderLiness { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>().HasMany<OrderLine>(o => o.Lines).WithRequired(l => l.Order);
}
}

Related

Entity Framework Core null relationship

I have created a simple EF Core to join two tables by using relationship (HasOne). But when I run it, the query only queries the master table (Employees) without joining to the second table (Contact) and it causes the model to not bind the data.
Could someone point out what I am missing in this code shown below? Thanks
public class Employees
{
public int EmployeeId { get; set; }
public string EmployeeName { get; set; }
public Contact Contact { get; set; }
}
public class Contact
{
public int Id { get; set; }
public string ContactNumber { get; set; }
public Employees Employee { get; set; }
public int EmployeeId { get; set; }
}
internal class EmployeeMap : IEntityTypeConfiguration<Employees>
{
public void Configure(EntityTypeBuilder<Employees> builder)
{
builder.HasKey(x => x.EmployeeId);
builder.Property(p => p.EmployeeId).ValueGeneratedOnAdd();
builder.HasOne(x => x.Contact).WithOne(y => y.Employee).HasForeignKey<Contact>(k => k.EmployeeId);
}
}
public class ContactMap : IEntityTypeConfiguration<Contact>
{
public void Configure(EntityTypeBuilder<Contact> builder)
{
builder.HasKey(x => x.Id);
builder.Property(p => p.Id).ValueGeneratedOnAdd();
}
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(GetType().Assembly);
}
private EmployeeResponse GetEmployeeResponse()
{
var emp = _context.Employees.FirstOrDefault();
return new EmployeeResponse
{
ContactNumber = emp!.Contact.ContactNumber,
EmployeeId = emp.EmployeeId,
};
}
Solutions:
1. Enable lazy loading:
DbContext.Configuration.LazyLoadingEnabled = true;
2. Or load it manually with .Include:
_context.Employees.Include(x => x.Contact).FirstOrDefault();
More information about navigation propertys in ef.

Can not set up one to many relationship with EF fluent API

I am trying to configure a one to many relationship using EF Core via fluent api and i keep getting the following error :
The expression 'x => x.parent' is not a valid property expression. The
expression should represent a simple property access: 't =>
t.MyProperty'. (Parameter 'propertyAccessExpression')'
Model(s)
public class Parent {
public int ID { get; set; }
public string Name { get; set; }
public ICollection<Child> Children { get; set; }
}
public class Child {
public int ID { get; set; }
public string Name { get; set; }
public Parent parent;
public int ParentId { get; set; }
}
Context
public class MyContext : DbContext {
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Children { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Child>().HasKey(x => x.ID);
modelBuilder.Entity<Parent>().HasKey(x => x.ID);
modelBuilder.Entity<Child>()
.HasOne(x => x.parent)
.WithMany(y => y.Children)
.HasForeignKey(t => t.ParentId);
}
public MyContext(DbContextOptions options):base(options) { }
}
Usage
static async Task Main(string[] args)
{
string connectionString = "[someconnectionstring]"
var optionsBuilder = new DbContextOptionsBuilder<MyContext>();
optionsBuilder.UseSqlServer(connectionString);
MyContext context = new MyContext(optionsBuilder.Options);
await context.Parents.AddAsync(new Parent {
Name = "myparent",
Children = new List<Child>() {
new Child { Name = "Child1" },
new Child { Name = "Child2" } }
}); //i am getting the error here
await context.SaveChangesAsync();
}
parent in Child class is a field. It should be public property. Please see for more information https://learn.microsoft.com/en-us/ef/ef6/modeling/code-first/fluent/types-and-properties#property-mapping

ASP.Net Core EF M-M Instance Cannot be Tracked

Consider the following error:
InvalidOperationException: The instance of entity type 'OrderRegion' cannot be tracked because another instance with the key value '[Orderid: 10, RegionId: 1]' is already being tracked...
Also, consider the following classes (slightly snipped for brevity):
public class Order
…
[Key]
public int Id { get; set; }
…
[Display(Name = "Regions")]
public ICollection<OrderRegion> OrderRegions { get; set; }
[Display(Name = "Stores")]
public ICollection<OrderStore> OrderStores { get; set; }
public class OrderRegion
{
//[Key]
public int OrderId { get; set; }
public Order Order { get; set; }
//[Key]
public int RegionId { get; set; }
public Region Region { get; set; }
}
public class OrderStore
{
//[Key]
public int OrderId { get; set; }
public Order Order { get; set; }
//[Key]
public int StoreId { get; set; }
public Store Store { get; set; }
}
Also of relevance is the Context where I create the relationships:
public class MyContext:DbContext
{
public MyContext(DbContextOptions<AzureOrdersContext> options) : base(options) { }
public DbSet<Order> Order { get; set; }
public DbSet<OrderRegion> OrderRegion { get; set; }
public DbSet<OrderStore> OrderStore { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
…
modelBuilder.Entity<OrderRegion>()
.HasKey(nr => new { nr.OrderId, nr.RegionId });
modelBuilder.Entity<OrderRegion>()
.HasOne(nr => nr.Order)
.WithMany(n => n.OrderRegions)
.HasForeignKey(nr => nr.OrderId);
modelBuilder.Entity<OrderRegion>()
.HasOne(nr => nr.Region)
.WithMany(n => n.OrderRegions)
.HasForeignKey(nr => nr.RegionId);
modelBuilder.Entity<OrderStore>()
.HasKey(nr => new { nr.OrderId, nr.StoreId });
modelBuilder.Entity<OrderStore>()
.HasOne(nr => nr.Order)
.WithMany(n => n.OrderStores)
.HasForeignKey(nr => nr.OrderId);
modelBuilder.Entity<OrderStore>()
.HasOne(nr => nr.Store)
.WithMany(n => n.OrderStores)
.HasForeignKey(nr => nr.StoreId);
}
}
And finally, my "Edit.cshtml.cs" where my error is thrown (snipped a lot):
public async Task<IActionResult> OnPostAsync(int? id, int[] AssignedRegions, int[] AssignedStores)
{
if (!ModelState.IsValid)
{
return Page();
}
var Ordertoupdate = await _context.Order
.Include(i => i.OrderRegions).ThenInclude(navigationPropertyPath: i => i.Region)
.Include(i => i.OrderStores).ThenInclude(navigationPropertyPath: i => i.Store)
.FirstOrDefaultAsync(m => m.Id == id);
...
if (await TryUpdateModelAsync<Web.Models.Order>(
Ordertoupdate,
"Order",
i => i.CreatedOn,
i => i.CreatedBy,
i => i.ModifiedBy, i => i.ExpirationDate,
...))
{
UpdateOrderRegions(_context, AssignedRegions, Ordertoupdate);
UpdateOrderStores(_context, AssignedStores, Ordertoupdate);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
UpdateOrderRegions(_context, AssignedRegions, Ordertoupdate);
UpdateOrderStores(_context, AssignedStores, Ordertoupdate);
PopulateAssignedRegions(_context, Ordertoupdate);
PopulateAssignedStores(_context, Ordertoupdate);
return Page();
}
The error is getting thrown on _context.SaveChangesAsync(); Any ideas? I'm certain I'm just doing something stupid and not seeing a simple fix.
Updating to include UpdateOrderRegions as requested:
public void UpdateOrderRegions (AzureOrdersContext _context, int[] SelectedRegions, Web.Models.Order OrderToUpdate)
{
if (SelectedRegions == null)
{
OrderToUpdate.OrderRegions = new List<OrderRegion>();
return;
}
var StoreRegionsToDelete= OrderToUpdate.OrderRegions.Where<OrderRegion>(nr => {
return !SelectedRegions.AsQueryable<Int32>().Contains<Int32>(nr.RegionId);
});
StoreRegionsToDelete.ToList().ForEach(r => { OrderToUpdate.OrderRegions.Remove(r); });
var StoreRegionsToAdd = SelectedRegions.AsQueryable<Int32>().Where<Int32>(regionId =>
!OrderToUpdate.OrderRegions.Any( nr=> nr.RegionId == regionId)
);
StoreRegionsToAdd.ToList().ForEach(regionId =>
OrderToUpdate.OrderRegions.Add(new OrderRegion
{
OrderId = OrderToUpdate.Id,
RegionId = regionId
}));
////This is where a different, more frustrating logical error lives but isn't related to my EF error
////Attempting to model after: https://github.com/aspnet/Docs/blob/master/aspnetcore/data/ef-rp/intro/samples/cu/Pages/Instructors/InstructorCoursesPageModel.cshtml.cs
var selectedRegionHS = new HashSet<string>(SelectedRegions);
var regionOrders = new HashSet<int>(OrderToUpdate.OrderRegions.Select(c => c.Order.Id));
foreach (var thisregion in _context.Region)
{
if (selectedRegionHS.Contains(thisregion.Id.ToString()))
{
if (!regionOrders.Contains(thisregion.Id))
{
OrderToUpdate.OrderRegions.Add(
new OrderRegion
{
OrderId = OrderToUpdate.Id,
RegionId = thisregion.Id
});
}
}
else
{
if (regionOrders.Contains(thisregion.Id))
{
OrderRegion RegionToRemove = OrderToUpdate.OrderRegions.SingleOrDefault(i => i.RegionId == thisregion.Id);
_context.Remove(RegionToRemove);
}
}
}
}
This issue occurs when the context already has an item tracked and you explicitly try attaching a new object with the same key.
Considering the error is on OrderRegion and this type has a composite key of OrderId/RegionId, I think it is likely that you are retrieving the OrderRegion and attaching a new OrderRegion with the same OrderId/RegionId combination. You may need to check if an OrderRegion key already exists or clear the Order's regions and rebuild the list to avoid this collision.
I hope this points you in the right direction. Feel free to provide the code where you handle the OrderRegion updates and I'll try to further assist.

The Entity create an additional table for many to-many relationships

Today I got a question about how to create a many to many mapping using Entity Framework Code First fluent api.
The problem is that the entity create an additional table beyond that was set for me.
public class Person
{
public Person()
{
courses = new HashSet<Course>();
}
public int PersonID { get; set; }
public String Name { get; set; }
public ICollection<Course> courses { get; set; }
}
public class Course
{
public Course()
{
people = new HashSet<Person>();
}
public int CourseID { get; set; }
public String Name { get; set; }
public ICollection<Person> people { get; set; }
}
public class PersonCourse
{
public int fk_CourseID { get; set; }
public virtual Course course { get; set; }
public int fk_PersonID { get; set; }
public virtual Person person { get; set; }
public String AnotherInformation { get; set; }
}
public class PersonDataConfiguration : EntityTypeConfiguration<Person>
{
public PersonDataConfiguration()
{
ToTable("Person");
Property(c => c.Name).IsRequired();
this.HasMany(c => c.courses).WithMany(t => t.people).Map(m => { m.MapLeftKey("CourseID"); m.MapRightKey("PersonID"); });
}
}
public class CourseDataConfiguration : EntityTypeConfiguration<Course>
{
public CourseDataConfiguration()
{
ToTable("Course");
Property(c => c.Name).IsRequired();
this.HasMany(c => c.people).WithMany(t => t.courses).Map(m => { m.MapLeftKey("PersonID"); m.MapRightKey("CourseID"); });
}
}
public class PersonCourseDataConfiguration : EntityTypeConfiguration<PersonCourse>
{
public PersonCourseDataConfiguration()
{
ToTable("PersonCourseX");
HasKey(c => new { c.fk_CourseID, c.fk_PersonID });
Property(c => c.AnotherInformation).IsRequired();
this.HasRequired(c => c.person).WithMany().HasForeignKey(t => t.fk_PersonID);
this.HasRequired(c => c.course).WithMany().HasForeignKey(t => t.fk_CourseID);
}
}
public class ProgramTesteContext : DbContext
{
public ProgramTesteContext()
: base("MyConnectionString")
{
}
public DbSet<Person> Person { get; set; }
public DbSet<Course> Course { get; set; }
public DbSet<PersonCourse> PersonCourse { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>();
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Properties<String>()
.Configure(p => p.HasColumnType("varchar"));
modelBuilder.Properties<String>()
.Configure(p => p.HasMaxLength(100));
modelBuilder.Configurations.Add(new PersonDataConfiguration());
modelBuilder.Configurations.Add(new CourseDataConfiguration());
modelBuilder.Configurations.Add(new PersonCourseDataConfiguration());
}
}
The entity set up two tables for mapping:
PersonCourseX created by me and another CoursePerson table containing only foreign keys without anotherinformation field.
How to make this second table is not created?
Change PersonCourseDataConfiguration as follows:
public class PersonCourseDataConfiguration : EntityTypeConfiguration<PersonCourse>
{
public PersonCourseDataConfiguration()
{
ToTable("PersonCourseX");
HasKey(c => new { c.fk_CourseID, c.fk_PersonID });
Property(c => c.AnotherInformation).IsRequired();
this.HasRequired(c => c.person).WithMany(c => c.courses).HasForeignKey(t => t.fk_PersonID);
this.HasRequired(c => c.course).WithMany(c => c.people).HasForeignKey(t => t.fk_CourseID);
}
}
Remove the commented lines:
public class PersonDataConfiguration : EntityTypeConfiguration<Person>
{
public PersonDataConfiguration()
{
ToTable("Person");
Property(c => c.Name).IsRequired();
//this.HasMany(c => c.courses).WithMany(t => t.people).Map(m => { m.MapLeftKey("CourseID"); m.MapRightKey("PersonID"); });
}
}
public class CourseDataConfiguration : EntityTypeConfiguration<Course>
{
public CourseDataConfiguration()
{
ToTable("Course");
Property(c => c.Name).IsRequired();
//this.HasMany(c => c.people).WithMany(t => t.courses).Map(m => { m.MapLeftKey("PersonID"); m.MapRightKey("CourseID"); });
}
}
Change Person and Course as follows:
public class Person
{
//.. other properties
public ICollection<PersonCourse> courses { get; set; }
}
public class Course
{
//.. other properties
public ICollection<PersonCourse> people { get; set; }
}

EF query not returning foreign key value of navigation property

I'm using EF5 Code First and Lazy Loading is disabled. I have the following code:
//Model
public class Task
{
public Guid Id {get; set;}
//other properties that are not relevant here
public Guid CreatorId {get; set;}
public User Creator {get; set;}
public Guid? OwnerId {get; set;}
public User Owner {get; set;}
}
//Model
public class User
{
public Guid Id { get; set; }
//other properties that are not relevant here
public string UserName { get; set; }
public IList<Task> TasksCreated { get; set; }
public IList<Task> TasksOwned { get; set; }
}
//Configuration for Task
public class TaskConfiguration : EntityTypeConfiguration<Task>
{
public TaskConfiguration()
{
HasRequired(task => task.Creator)
.WithMany(creator => creator.TasksCreated)
.HasForeignKey(task => task.CreatorId)
.WillCascadeOnDelete(false);
HasOptional(task => task.Owner)
.WithMany(owner => owner.TasksOwned)
.HasForeignKey(task => task.OwnerId)
.WillCascadeOnDelete(false);
}
}
When I query against Tasks, all the data comes back as expected. When I query against Users using the following query, the Tasks property for Owner or Creator is null. The null value is assigned to whatever property does not match the User I am querying for. So, if User2 is the Owner on User1's Task, User2's ID will come back, but the Owner property will be null. This is the query:
var db = new MyContext();
var user = db.Users
.Include("TasksCreated")
.Include("TasksOwned")
.SingleOrDefault(u => u.UserName.Equals("user1", StringComparison.OrdinalIgnoreCase));
I'm not sure if there is another step I'm missing or if I don't have the proper configuration for the Task-User relationship. Any help is appreciated.
i try your code and it runs.
The only difference is the constructor of the context I add:
public class TestEFContext : DbContext {
public IDbSet<User> us { get; set; }
public IDbSet<Task> ts { get; set; }
public TestEFContext(String cs)
: base(cs) {
Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
Configuration.LazyLoadingEnabled = false;
modelBuilder.Configurations.Add(new TaskConfiguration());
}
}
from here the following :
class Program {
static void Main(String[] args) {
String cs = #"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";
using (TestEFContext c = new TestEFContext(cs)) {
User u1 = new User {
Id = Guid.NewGuid(),
UserName = "u1"
};
User u2 = new User {
Id = Guid.NewGuid(),
UserName = "u2"
};
c.us.Add(u1);
c.us.Add(u2);
Task t = new Task {
Id = Guid.NewGuid(),
Creator = u1,
Owner = u1
};
c.ts.Add(t);
t = new Task {
Id = Guid.NewGuid(),
Creator = u2,
Owner = u1
};
c.ts.Add(t);
c.SaveChanges();
}
using (TestEFContext c = new TestEFContext(cs)) {
var user = c.us
.Include("TasksCreated")
.Include("TasksOwned")
.SingleOrDefault(u => u.UserName.Equals("u1", StringComparison.OrdinalIgnoreCase));
foreach (Task t in user.TasksCreated) {
Console.WriteLine(t.Id);
}
Console.WriteLine("-----");
foreach (Task t in user.TasksOwned) {
Console.WriteLine(t.Id);
}
}
}
}
displays as expected:
a415c8c6-6b0a-4e1b-a42f-cd4230cf4d4a
-----
a415c8c6-6b0a-4e1b-a42f-cd4230cf4d4a
a2e9c527-d8cb-4db7-8879-7febb1c30a07
Appuyez sur une touche pour continuer...
EDITION ========== ==========
the following code runs also:
using System;
using System.Linq;
using System.Data.Entity;
using System.Collections.Generic;
using System.Data.Entity.ModelConfiguration;
namespace testef {
//Model
public class Task {
public Guid Id { get; set; }
//other properties that are not relevant here
public String ShortDescription { get; set; }
public Guid CreatorId { get; set; }
public User Creator { get; set; }
public Guid? OwnerId { get; set; }
public User Owner { get; set; }
}
//Model
public class User {
public Guid Id { get; set; }
//other properties that are not relevant here
public string UserName { get; set; }
public IList<Task> TasksCreated { get; set; }
public IList<Task> TasksOwned { get; set; }
}
//Configuration for Task
public class TaskConfiguration : EntityTypeConfiguration<Task> {
public TaskConfiguration() {
HasRequired(task => task.Creator)
.WithMany(creator => creator.TasksCreated)
.HasForeignKey(task => task.CreatorId)
.WillCascadeOnDelete(false);
HasOptional(task => task.Owner)
.WithMany(owner => owner.TasksOwned)
.HasForeignKey(task => task.OwnerId)
.WillCascadeOnDelete(false);
}
}
public class TestEFContext : DbContext {
public IDbSet<User> us { get; set; }
public IDbSet<Task> ts { get; set; }
public TestEFContext(String cs)
: base(cs) {
Database.SetInitializer<TestEFContext>(new DropCreateDatabaseAlways<TestEFContext>());
}
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
base.OnModelCreating(modelBuilder);
Configuration.LazyLoadingEnabled = false;
modelBuilder.Configurations.Add(new TaskConfiguration());
}
}
class Program {
static void Main(String[] args) {
String cs = #"Data Source=ALIASTVALK;Initial Catalog=TestEF;Integrated Security=True; MultipleActiveResultSets=True";
using (TestEFContext c = new TestEFContext(cs)) {
User u1 = new User {
Id = Guid.NewGuid(),
UserName = "u1"
};
User u2 = new User {
Id = Guid.NewGuid(),
UserName = "u2"
};
c.us.Add(u1);
c.us.Add(u2);
Task t = new Task {
Id = Guid.NewGuid(),
ShortDescription = "t1",
Creator = u1,
Owner = u1
};
c.ts.Add(t);
t = new Task {
Id = Guid.NewGuid(),
ShortDescription = "t2",
Creator = u2,
Owner = u1
};
c.ts.Add(t);
c.SaveChanges();
}
using (TestEFContext c = new TestEFContext(cs)) {
var user = c.us
.Include("TasksCreated")
.Include("TasksOwned")
.SingleOrDefault(u => u.UserName.Equals("u1", StringComparison.OrdinalIgnoreCase));
foreach (Task t in user.TasksCreated) {
Console.WriteLine("{0} - {1} is owned by {2}, was created by {3} ", t.ShortDescription, t.Id, t.OwnerId, t.CreatorId);
}
Console.WriteLine("-----");
foreach (Task t in user.TasksOwned) {
Console.WriteLine("{0} - {1} is owned by {2}, was created by {3} ", t.ShortDescription, t.Id, t.OwnerId, t.CreatorId);
}
}
}
}
}