I feel like I'm missing some basic setup step here, but I've been wading through forum posts, blog articles, and videos for hours and keep having the same problem, so I figure it's time to post.
The error I'm getting is:
Mapping and metadata information could not be found for EntityType 'qTrade.BusinessLayer.Domain.Model.Audit.LoanPool'.
I've got an Entity Model file called Audit.edmx that has code generation turned off. In there I generated an Entity from the database for this table (pasted from the create script, LoanPoolAuditId is the Primary Key):
CREATE TABLE [Audit].[LoanPool](
[Type] [char](1) NULL,
[TableName] [varchar](128) NULL,
[PK] [varchar](1000) NULL,
[FieldName] [varchar](128) NULL,
[OldValue] [varchar](1000) NULL,
[NewValue] [varchar](1000) NULL,
[UpdateDate] [datetime] NULL,
[UserName] [varchar](128) NULL,
[CommonID] [int] NULL,
[LoanPoolAuditId] [int] IDENTITY(1,1) NOT NULL,
I've got a class I created to be a POCO elsewhere in the same project
public class LoanPool
{
public int CommonID { get; set; }
public string FieldName { get; set; }
public int LoanPoolAuditId { get; set; }
public string NewValue { get; set; }
public string OldValue { get; set; }
public string PK { get; set; }
public string TableName { get; set; }
public char Type { get; set; }
public DateTime UpdateDate { get; set; }
public string UserName { get; set; }
}
And I've got the context class
public class AuditContext : ObjectContext
{
public AuditContext()
: base("name=AuditEntities", "AuditEntities")
{
this.LoanPools = CreateObjectSet<LoanPool>();
}
public ObjectSet<LoanPool> LoanPools { get; set; }
}
Heres the connection string for reference
"metadata=res://*/EntityModels.Audit.csdl|res://*/EntityModels.Audit.ssdl|res://*/EntityModels.Audit.msl;provider=System.Data.SqlClient;provider connection string="data source=serverName;initial catalog=databaseName;persist security info=True;user id=*SNIP*;password=*SNIP*;multipleactiveresultsets=True;App=EntityFramework""
Very simple (or so I thought).
When I go to instantiate an instance of the context I get the aforementioned error on the CreateObjectSet step.
Any suggestions would be greatly appreciated, even if they are simple or obvious, this is my first time using POCOs so there's a good chance I missed something.
Go figure I had no trouble using code-first in a different project :-P
Thanks
We generally recommend using DbContext as the primary means of operating with anything EF 4.1 or beyond. In this case you would need to get rid of your existing .edmx and modify your AuditContext as follows:
public class AuditContext : DbContext
{
public DbSet<LoanPool> LoanPools { get; set; }
}
You can also see the corresponding walkthrough on the official blog here: http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-code-first-walkthrough.aspx. Also, you will need to put the [Key] attribute on LoanPoolAuditId as it does not conform to the expected conventions. That's also mentioned in the blog post.
HTH,
Mark
Related
Is there an easy way to have a setup like this in EF Core?
ProjectEntity
Id
Name
List<Notes>
CustomerEntity
Id
Name
List<Notes>
NotesEntity
Id
Date
Note
Every parent entity would have a one-to-many relation to same child entity. So I can not use normal behavior as
NotesEntity
Id
ParentId
Date
Note
I have some idea to have like above but also add one field that said what the parent entity is, is that the right way to do it or is there a better way? If I use this way I can't use EF Core normal behavior with one-to-many relationship? I need to make more manual work for search / add and so on?
Edit :
Entity Framework multiple parent tables I found this solution, but there I need to make a connection from my child to every parent I use, it could be alot of them.
Did also find a solution like :
BaseEntity
List<Notes>
ProjectEntity:BaseEntity
NotesEntity
Id
BaseEntityId
...
This last solution maybe is the best way to do it if I have alot of parent entities?
[EDIT 220922]
Could [Owned] type has collection of other Items? Or this feature won't work on owned entitys? I guess this behavior isn't supported?
[Owned]
public class Note
{
public int Id { get; set; }
public string Text { get; set; }
public int UserId { get; set; }
public User User { get; set; }
public ICollection<string> Tags { get; set; }
}
I got an error on ICollection-row when I try to add-migration.
Unabel to determine the relationshop represented by navigation ... of
typ 'ICollection' Either manually configure the relationship, or
ignore this property using the '[NotMapped]' attribute.....
Maybe I could have one middleentity like :
public class NoteTagsEntity
{
public int Id { get; set; }
public ICollection<string> Tags { get; set; }
}
And then :
[Owned]
public class Note
{
public int Id { get; set; }
public string Text { get; set; }
public int UserId { get; set; }
public User User { get; set; }
public int NoteTagsId { get; set; }
public NoteTagsId NoteTagsId { get; set; }
}
Edit
I solved the Note functionality with having more FK's, one that point to Id of parent and one FK Id that point to what module that use that particular note. Here I don't have parent - child relation in my entities, I need to do this connection by myself but in this way it's easy to apply more modules that use note's later.
Use Owned Entity Types, and each entity will get its own notes table.
eg
public abstract class Entity
{
public int Id { get; set; }
}
public abstract class EntityWithNotes: Entity
{
public virtual ICollection<Note> Notes { get; set; }
}
[Owned]
public class Note
{
public int Id { get; set; }
public string Text { get; set; }
}
public class Project : EntityWithNotes
{
public string Name { get; set; }
}
public class Customer : EntityWithNotes
{
public string Name { get; set; }
}
creates
CREATE TABLE [Customer_Notes] (
[Id] int NOT NULL IDENTITY,
[CustomerId] int NOT NULL,
[Text] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Customer_Notes] PRIMARY KEY ([CustomerId], [Id]),
CONSTRAINT [FK_Customer_Notes_Customer_CustomerId] FOREIGN KEY ([CustomerId]) REFERENCES [Customer] ([Id]) ON DELETE CASCADE
);
CREATE TABLE [Project_Notes] (
[Id] int NOT NULL IDENTITY,
[ProjectId] int NOT NULL,
[Text] nvarchar(max) NOT NULL,
CONSTRAINT [PK_Project_Notes] PRIMARY KEY ([ProjectId], [Id]),
CONSTRAINT [FK_Project_Notes_Project_ProjectId] FOREIGN KEY ([ProjectId]) REFERENCES [Project] ([Id]) ON DELETE CASCADE
);
I´m currently learning to use EF and I have the following relationships:
An Alert has 1 to n occurences.
Each occurence can have 0 to n values (additional information).
public class Alert
{
// PK
public int AlertId { get; set; }
// Attributes
public int CurrentAlertLevel { get; set; }
public DateTime TimeRaised { get; set; }
public DateTime TimeLastRaised { get; set; }
// Some other attributes ommitted...
// Relations
public ICollection<AlertOccurrence> Occurrences { get; set; }
}
public class AlertOccurrence
{
// Relations which are part of the primary key
public int AlertId { get; set; }
// Attributes
public int Ordinal { get; set; }
// some ommited attributes
// Relations
public ICollection<AlertDetailValue> AlertDetailValues { get; set; }
}
public class AlertDetailValue
{
public int AlertDetailValueId { get; set; }
public int Order { get; set; }
public string Value { get; set; }
}
In the DB Context OnModelCreating I´m setting the combined PK for AlertOccurence:
modelBuilder.Entity<AlertOccurrence>().HasKey(ao => new {ao.AlertId, ao.Ordinal});
While it seems that this is working - what I would actually like to archive is the same relationship without the need to have the AlertDetailValueId as PK. The table that EF generates also includes AlertOccurrenceAlertId and AlertOccurrenceOrdinal which seems a waste of space to me.
So what I would like to do is:
Have a combined primary key for AlertDetailValue consisting of AlertDetailValue.Order and the (already combined) PK of AlertOccurence instead of the "artificial" AlertDetailValueId. Is that even possible ?
Part of my problem might be that the PK defined using the fluent api is not part of the data classes. So probably another question to ask would be: Is there a way to use a key defined in fluent api in a entity class ?
Or do I need to include AlertOccurrenceAlertId and AlertOccurrenceOrdinal in my entity class AlertDetailValue - but how do I link them then ?
As I said I´m still trying to get my head around EF so while there might be better ways to do this I´m interested in this special kind of relation / combined(combined) PK even if it might be academic... Any help would be highly appreciated.
Trying to explain what I try to do and what my problem is - and taking a good shower - helped me to ask different questions to google and focus more on the foreign key.
It´s not that I did not try to google it before... I just asked the wrong questions..
So I found this:
Mapping composite foreign key to composite primary key where the foreign key is also a primary key
(While trying the new approch #atiyar also hinted on the missing foreign key...)
My new solution was to change AlertDetailValue to intentionally include the parts that the Occurence PK is build of:
public class AlertDetailValue
{
// relations will be set up in fluent api in OnModelCreating of db context
public int AlertOccurenceAlertId { get; set; }
public int AlertOccurenceOrdinal { get; set; }
public int Order { get; set; }
public string Value { get; set; }
}
And then to tell EF that there is a combined PK and also a combined foreign key:
modelBuilder.Entity<AlertDetailValue>().HasKey(adv => new { adv.AlertOccurenceAlertId, adv.AlertOccurenceOrdinal, adv.Order });
modelBuilder.Entity<AlertOccurrence>().HasMany<AlertDetailValue>(adv => adv.AlertDetailValues).WithOne()
.HasForeignKey(adv => new {adv.AlertOccurenceAlertId, adv.AlertOccurenceOrdinal});
I have a problem with Entity Framework (6, not Core). I already tried several things and googled around but I can't figure it out so I'm asking here.
Thats my db-scheme:
CREATE TABLE MyItem
(
[Id] int IDENTITY(1,1) NOT NULL,
[Name] varchar(100) NOT NULL,
[Start] date NOT NULL,
[End] date NOT NULL
)
And these are my classes:
public class MyItem
{
public int Id { get; set; }
public string Name { get; set; }
public MyTimespan IsValidTimespan { get; set; }
}
public class MyTimespan
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
}
I want to map
the value from "MyItem.IsValidTimespan.Start" to the "Start"-column
the value from "MyItem.IsValidTimespan.Ende" to the "Ende"-column
I already tried different things with Attributes on the MyTimespan-class ("ComplexType" and "Column" Attributes) and also some hacks with the modelBuilder, nothing worked.
How can I get this to work?
Thank you and best regards,
Alex
Ok I got it. The code I posted above is not 100% correct: the properties of MyTimespan did not had setters. The following changes in "MyTimespan" did it:
adding the annotations mentioned in my question
adding private setters to the properties
adding a private default constructor
At the biginning, I defined the model like this:
public class Category
{
public long CategoryId { get; set;}
public string CategoryName { get; set; }
public virtual ICollection<ContentInfo> Contents { get; set; }
}
Public class Article
{
public int ContentId { get; set; }
public string Content { get; set; }
[ForeignKey("Category")]
public long CategoryId { get; set; }
public virtual Category Category { get; set; }
}
After generating the database from the model with Automatic-Migration, I changed the CategoryId's type from "long" to "int", and update the database with Automatic-Migration again.
This time an exception was throwed, telling me The column "CategoryId" was referenced by Primary key and Foreign Key, so the migration is failed. If i delete the Primary key and Foreign Key manually, everything is ok. but i want the Automatic-Migration to do this for me, can it?
Havent tries such a migration myself, but i recall seeing an option
public class MYMigrationConfiguration : DbMigrationsConfiguration
{
public MyMigrationConfiguration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true; //have you tried this ?
}
Otherwise you may need to do a code based migration for this type of change
You can use the "Sever Explore" and manually manipulate the table structure, e.g., dropping the key constraints, or delete the whole table. And let EF to generate the brand new table definitions.
I have an app that was created using EF. The problem is that I noticed some extraneous foreign keys columns created in one of the tables. Dropping these columns causes an [SqlException (0x80131904): Invalid column name 'Material_Id' error.
Here is a simplified version of the class structure...
public class Hazard
{
public int Id { get; set; }
public string Name { get; set; }
}
public abstract class HazardAnalysis
{
public int Id { get; set; }
public int HazardId { get; set; }
public virtual Hazard Hazard { get; set; }
}
public class ProductHazard : HazardAnalysis
{
public int ProductId { get; set; }
public virtual Product Product { get; set; }
}
The table that was generated looked like this...
dbo.Hazards
Id int
Name string
Product_Id int
Since the relationship between ProductHazards and Hazards is 1:many, the Product_Id field should not be there. Dropping this column generates the Invalid column name 'Product_Id' error.
I've scoured the model for hours and can't find any valid reason for this column to exist.
Is there any way to update the model after manually dropping a column? I obviously don't want to drop and recreate the database.
I've also noticed that the productId of the current product is inserted in the dbo.Hazards Product_Id table whenever a new ProductHazard is created. Since there is a many-to-one relationship between ProductHazards and Hazards, when a new ProductHazard is created, the Product_Id field is updated with the ProductId of the new ProductHazard, which seems bizarre.
Any advice would be greatly appreciated.
Here is the DbSet code:
public DbSet<Hazard> Hazards { get; set; }
public DbSet<HazardAnalysis> HazardAnalyses { get; set; }
and also...
modelBuilder.Entity<HazardAnalysis>()
.HasRequired(e => e.Hazard)
.WithMany()
.HasForeignKey(e => e.HazardId)
.WillCascadeOnDelete(false);
You need to define the many part of the relationship. In this case, you need to add a collection property to your Hazard object, like below:
public class Hazard
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<HazardAnalysis> HazardAnalyses { get; set; }
}