I'm using Entity Framework 6.0 and have defined 2 POCO's to map to my database:
[Table("PortfolioGroups")]
public class PortfolioGroup : AuditableEntity<int>
{
[Column("Company_Id")]
public int CompanyId { get; set; }
[ForeignKey("CompanyId")]
public Company Company { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<PortfolioGroupItem> PortfolioGroupItems { get; set; }
public PortfolioGroup()
{
PortfolioGroupItems = new Collection<PortfolioGroupItem>();
}
}
And the PortfolioGroupItem:
[Table("PortfolioGroupItems")]
public class PortfolioGroupItem : AuditableEntity<int>
{
[Column("PortfolioGroup_Id")]
public int PortfolioGroupId { get; set; }
[ForeignKey("PortfolioGroupId")]
public PortfolioGroup PortfolioGroup { get; set; }
[Column("Trademark_Id")]
public int? TrademarkId { get; set; }
[ForeignKey("TrademarkId")]
public Trademark.Trademark Trademark { get; set; }
[Column("TrademarkRegistration_Id")]
public int? TrademarkRegistrationId { get; set; }
[ForeignKey("TrademarkRegistrationId")]
public TrademarkRegistration TrademarkRegistration { get; set; }
[Column("Domain_Id")]
public int? DomainId { get; set; }
[ForeignKey("DomainId")]
public Domains.Domain Domain { get; set; }
}
However - when I attempt to query the PortfolioGroups, Entity Framework for some reason attempts to query a field named "Trademark_Id" - which doesn't exist on the PortfolioGroup entity:
Context.PortfolioGroups.SingleOrDefault(i => i.Id == id && i.CompanyId == companyId);
Throws:
Invalid column name 'Trademark_Id'.
I've used this kind of setup other places in my application without any problems. I simply cannot find out why EF is trying to query a column that's not in my entity!
Any suggestions would be greatly appreciated. I'm at the end of my rope here.
Thanks guys! :)
The problem is that you've added a Navigation Property on Trademark that requires a Foreign Key on Portfolio Group:
public class Trademark
{
[Key]
public int Id { get; set; }
[MaxLength(250)]
[Required]
public string Name { get; set; }
[MaxLength(150)]
public string Filename { get; set; }
public ICollection<PortfolioGroup> PortfolioGroups { get; set; }
public Trademark()
{
PortfolioGroups = new Collection<PortfolioGroup>();
}
}
EF expects PortfolioGorup to have a Trademark_ID column to store which PortfolioGroups are associated with a Trademark.
Related
I'm using EF core, and I have a many-to-many relationship between two entity
IotaProject <--> User
Here's entities & dto related to the question
public class IotaProject
{
[Key]
public int Id { get; set; }
[Required]
public string ProjectName { get; set; }
[Required]
public DateTime Create { get; set; }
public ICollection<ProjectOwnerJoint> Owners { get; set; } = new List<ProjectOwnerJoint>();
}
public class ProjectOwnerJoint
{
public int IotaProjectId { get; set; }
public IotaProject IotaProject { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
public class User
{
[Key]
public int Id { get; set; }
[Required]
public string FullName { get; set; }
[Required]
public string ShortName { get; set; }
[Required]
public string Email { get; set; }
public ICollection<ProjectOwnerJoint> OwnedProjects { get; set; } = new List<ProjectOwnerJoint>();
}
public class ApplicationDbContext : DbContext
{
public DbSet<IotaProject> IotaProjects { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<ProjectOwnerJoint> ProjectOwnerJoint { get; set; }
}
public class IotaProjectDisplayDto
{
public int Id { get; set; }
public string ProjectName { get; set; }
public DateTime Create { get; set; }
public UserMinDto Owner { get; set; }
public int Count { get; set; }
public IEnumerable<UserMinDto> Reviewers { get; set; }
}
public class UserMinDto
{
public int Id { get; set; }
public string FullName { get; set; }
public string ShortName { get; set; }
}
Following LINQ is the problem, the LINQ purpose is to convert IotaProject to IotaProjectDisplayDto, and key part is that Owners property of IotaProject is ICollection and Owner property in IotaProjectDisplayDto is just one single element UserMinDto, so I only need to get the first element of IotaProject's Owners and that's FirstOrDefault() comes.
IEnumerable<IotaProjectDisplayDto> results = _db.IotaProjects.Select(x => new IotaProjectDisplayDto
{
Id = x.Id,
ProjectName = x.ProjectName,
Create = x.Create,
Owner = x.Owners.Select(y => y.User).Select(z => new UserMinDto { Id = z.Id, FullName = z.FullName, ShortName = z.ShortName }).FirstOrDefault()
});
return results;
it throws run-time exception
Expression of type 'System.Collections.Generic.List`1[ToolHub.Shared.iota.UserMinDto]' cannot be used for parameter
of type 'System.Linq.IQueryable`1[ToolHub.Shared.iota.UserMinDto]'
of method 'ToolHub.Shared.iota.UserMinDto FirstOrDefault[UserMinDto](System.Linq.IQueryable`1[ToolHub.Shared.iota.UserMinDto])' (Parameter 'arg0')
I'm guessing it's probably related to deferred execution, but after read some posts, I still can't resolve it.
Any tips would be appreciated.
Right now, the only way I can get this work is I change type of Owner property in IotaProjectDisplayDto into IEnumrable, which will no longer need FirstOrDefault() to immediate execution. And later on, I manually get the first element in the client to display.
This issue happened in Microsoft.EntityFrameworkCore.SqlServer 3.0.0-preview7.19362.6
I end up downgrade to EF core stable 2.2.6 as Ivan suggested in comment, and everything works fine.
This question already has answers here:
EF Core returns null relations until direct access
(2 answers)
Closed 4 years ago.
So I have 3 classes:
public class OwnerDto
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
}
public class SitterDto
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
}
public class ReviewDto
{
public int Id { get; set; }
public int Rating { get; set; }
//[ForeignKey("OwnerId")]
public OwnerDto Owner { get; set; }
//[ForeignKey("SitterId")]
public SitterDto Sitter { get; set; }
}
But I can't figure out how to do the proper modelBuilder. Everything I tried fails :( I am learning so bear with me.
My closest attempt was this:
modelBuilder.Entity<ReviewDto>()
.HasOne(t => t.Owner).WithMany().HasForeignKey("OwnerId");
Basically Owner and Sitter are always null :( Should i keep the [ForeignKey()] stuff or should i use a different extension method?
Declare all classes with navigation properties to each other. Mark one of the tables (the dependent table) with the ForeignKey attribute on its Primary Key.
EF infers one-to-many from this:
public class OwnerDto
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public ICollection<ReviewDto> Reviewers{ get; set; }
public ICollection<SitterDto> Sitters{ get; set; }
}
public class SitterDto
{
public int Id { get; set; }
public string Name { get; set; }
public string EmailAddress { get; set; }
public int OwnerId{ get; set; }
[ForeignKey("OwnerId")]
public OwnerDto Owner { get; set; }
}
public class ReviewDto
{
public int Id { get; set; }
public int Rating { get; set; }
public int OwnerId{ get; set; }
[ForeignKey("OwnerId")]
public OwnerDto Owner { get; set; }
}
and EF infers one-to-one from this:
public class OwnerDto
{
...
public ReviewDto Review{ get; set; }
...
}
public class ReviewDto
{
[ForeignKey("Owner")]
public int OwnerId { get; set; }
public OwnerDto Owner{ get; set; }
...
}
You need to refer Eager Loading in this scenario, You can use the Include method to specify related data to be includethe d in query results.
var query = from review in context.Review.Include(o => o.Owner).Include(s=>s.Sitter) select review;
My EF Code First model for some reason is not in sync with the db. I'm getting this error:
{"Invalid column name 'Type_Id1'."}
The field is actually called 'Type_Id' so I'm not sure from where that 1 comes up. I have the table column called as Type_Id and also I've added a Type_Id in my type entity model.
Why might I be getting that error message, plus why I'm getting 1 at the end of the name?
Update
My Task class:
public class Task
{
public Task()
{
Language = 1;
Grades = new HashSet<Grade>();
Categories = new HashSet<Category>();
Subjects = new HashSet<Subject>();
Rooms = new Collection<Room>();
Tools = new Collection<Tool>();
}
[Key]
public int Id { get; set; }
public string Description { get; set; }
public virtual TaskType Type { get; set; }
public string Rules { get; set; }
[Required]
[StringLength(200), MinLength(1)]
public string Name { get; set; }
public int PreperationTime { get; set; }
public int InstructionTime { get; set; }
public int TaskTime { get; set; }
public int Type_Id { get; set; }
public string VideoLink { get; set; }
[Required]
public int Language { get; set; }
public int? MinimumParticipants { get; set; }
public int? MaximumParticipants { get; set; }
public int? Rating { get; set; }
[Required]
public string CreatedBy { get; set; }
public virtual ICollection<Grade> Grades { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Subject> Subjects { get; set; }
public virtual ICollection<Room> Rooms { get; set; }
public virtual ICollection<Tool> Tools { get; set; }
}
DBContext class:
public ApplicationDbContext() : base("DefaultConnection", false)
{
}
public DbSet<Task> Tasks { get; set; }
public DbSet<TaskType> TaskTypes { get; set; }
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
You need to add the FK attribute on your navigation property. EF is creating Type_Id1 because Type_Id already exists (although it can't tell by convention it is the FK).
[ForeignKey("Type_Id")]
public virtual TaskType Type { get; set; }
https://msdn.microsoft.com/en-us/data/jj591583.aspx#Relationships
Following the example in this question: How to create a many-to-many mapping in Entity Framework? I would like to have a table mapping where I can add or remove many-to-many relationships without having to go through the Media or Contract entities.
Essentially, I would like to have:
public class Media // One entity table
{
public int Id { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public virtual ICollection<Contract> Contracts { get; set; }
}
public class Contract // Second entity table
{
public int Id { get; set; }
public string Code { get; set }
public virtual ICollection<Media> Medias { get; set; }
}
public class ContractMedia // Association table implemented as entity
{
public Media Media { get; set; }
public int MediaId { get; set; }
public Contract Contract { get; set; }
public int ContractId { get; set; }
}
Is it possible to configure this scenario using the FluentAPI?
afaik not with the ContractMedia entity, but you can:
public class Media // One entity table
{
public int Id { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public virtual ICollection<ContractMedia> Contracts { get; set; }
}
public class Contract // Second entity table
{
public int Id { get; set; }
public string Code { get; set }
public virtual ICollection<ContractMedia> Medias { get; set; }
}
public class ContractMedia // Association table implemented as entity
{
public Media Media { get; set; }
public int MediaId { get; set; }
public Contract Contract { get; set; }
public int ContractId { get; set; }
}
or
public class Media // One entity table
{
public int Id { get; set; }
public string Name { get; set; }
public bool Enabled { get; set; }
public virtual ICollection<Contract> Contracts { get; set; }
}
public class Contract // Second entity table
{
public int Id { get; set; }
public string Code { get; set }
public virtual ICollection<Media> Medias { get; set; }
}
that will lead to the creation of a non mapped association table in the database.
I created a WCF service with Entity Framework.
I have 2 tables : Theaters and Locality. Locality as a foreign key in Theaters.
My method :
public theater[] GetTheaters()
{
using (Entities context = new Entities())
{
return context.theater.ToArray();
}
}
I have to remove the "virtual" keyword from "public virtual locality locality { get; set; }" in my theater class. Otherwise, I get a CommunicationException.
But when I do that, I get my list of theaters but the locality is null...
How can I get the locality ?
Thanks
My model class ( I also have other entities) :
public partial class locality
{
public locality()
{
this.theater = new HashSet<theater>();
}
public int idLocality { get; set; }
public int npa { get; set; }
public string locality1 { get; set; }
public ICollection<theater> theater { get; set; }
}
public partial class theater
{
public theater()
{
this.session = new HashSet<session>();
}
public int idTheater { get; set; }
public string name { get; set; }
public string address { get; set; }
public int idLocality { get; set; }
public double latitude { get; set; }
public double longitude { get; set; }
public int seats { get; set; }
public string phone { get; set; }
public string email { get; set; }
public bool threeD { get; set; }
public locality locality { get; set; }
public ICollection<session> session { get; set; }
}
Here is the error that I get :
"Object graph for type 'locality' contains cycles and cannot be serialized if reference tracking is disabled.
EDIT :
The solution that I found :
In my locality class, I had a Collection of theaters.
I had to add "private to the setter like this :
" public ICollection theater { get; private set; }"
So it works, but I still have a problem, I can't access to the theaters from the locality entity anymore. (no more bi-directional)
If you want to force related entities to load, you can use the Include method to do so. By default, related entities are loaded Lazily.
Your example would be:
public theater[] GetTheaters()
{
using (Entities context = new Entities())
{
return context.theater.Include(t=>t.Locality).ToArray();
}
}
You can use eager loading or explicit loading. With eager loading you use the Include extension method:
return context.Theater.Include(t => t.Locality).ToArray();
You're missing the correct annotations to create the relationships. See the code below. (or create the relationships yourself if using the FluentAPI)
Look for the [Key] and [ForeignKey] annotations, as well as the virtual keyword.
public partial class locality
{
public locality()
{
//this.theater = new HashSet<theater>();
}
[Key]
public int idLocality { get; set; }
public int npa { get; set; }
public string locality1 { get; set; }
public virtual ICollection<theater> theaters { get; set; }
}
public partial class theater
{
public theater()
{
//this.session = new HashSet<session>();
}
[Key]
public int idTheater { get; set; }
public string name { get; set; }
public string address { get; set; }
public int idLocality { get; set; }
public double latitude { get; set; }
public double longitude { get; set; }
public int seats { get; set; }
public string phone { get; set; }
public string email { get; set; }
public bool threeD { get; set; }
[ForeignKey("idLocality")]
public virtual locality locality { get; set; }
//public ICollection<session> session { get; set; }
}