I have a ASP.NET MVC + EF web application, but I get an error when trying to query a list of Product using LINQ:
Invalid column name 'Discriminator'. Invalid column name 'NewProductPhoto'
This happened after I added a derived class from one of my entities.
My entity class:
[Table("Product")]
public partial class Product
{
public Product()
{
ProductPhotos = new HashSet<ProductPhoto>();
SalesOrderItems = new HashSet<SalesOrderItem>();
}
// more attributes here
}
My new derived class:
public class ProductEx : Product
{
public byte[] NewProductPhoto { get; set; }
}
I understand that EF tries to distinguish between Product and ProductEx but the point is I have no intention to add ProductEx to EF model.
I don't know why it considers ProductEx as part of database model.
How can I tell EF to not consider ProductEx as database model.
I found that the same way I can exclude a property from entity framework persistent, I can exclude my ProductEx class from entity framework modeling.
The attribute [NotMapped] does the trick.
[NotMapped]
public class ProductEx : Product
{
public byte[] NewProductPhoto { get; set; }
}
I still don't understand why EF even considers my derived class for persistence.
Related
I have (can`t change) EF DataBase first project without navigation property in models.
I want extend autogenerated models and add navigation property
Generated model
//generated.cs
public partial class company
{
public int id { get; set; }
public string name { get; set; }
}
public partial class user
{
public int id { get; set; }
public int company_id { get; set; }
}
I want add navigation property from code
//model_extension.cs
public partial class user
{
public company Company { get; set; }
}
I have exception "The specified type member 'Company' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported."
I work with CodeFirst before.
I understand, I must link user.company_id to Company
But not understand how make this with code (not designer)
In Database First Approach, You are generating your POCO objects from database schema via Entity Framework Designer/ADO.NET Entity Data Model so it is not flexible as Code-First, you need to go on database, and change the schema yourself and update your .edmx file. while adding properties to these Models are possible in c# side, but they are not going to be added to your database schema,
I suggest your reverse your database schema and go as Code-First Approach, This nuget package can do this for you.
After Reversing It's all about Code-First then, creating your own DbContext and OnModelCreating and let the Migration handle the rest. Then you can use Eager Loading of EF to load your data,
I have a SQL view that I am pulling in with entity framework. The view represents two existing objects that are joined together. I figured the best way to do this would be to have object inherit the other object.
I'm getting this error:
System.Data.Entity.Core.EntityCommandExecutionException: An error
occurred while executing the command definition. See the inner
exception for details. ---> System.Data.SqlClient.SqlException:
Invalid column name 'Discriminator'.
Here is what I have setup:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Class1>()
.ToTable("mySQLView", "TEST")
.HasKey(r => new { r.Property1 });
modelBuilder.Entity<Class1>().Property(r => r.Property1).HasColumnName("Key1");
modelBuilder.Entity<Class1>().Property(r => r.Property2).HasColumnName("Column2");
modelBuilder.Entity<Class1>().Property(r => r.Property3).HasColumnName("Column3");
modelBuilder.Entity<Class1>().Property(r => r.Property4).HasColumnName("Column4");
}
Here are my two classes:
public class Class1 : Class2
{
public string Property1 { get; set; }
public string Property2 { get; set; }
}
public class Class2
{
public string Property3 { get; set; }
public string Property4 { get; set; }
}
Class2 is being utilized by separate DB calls. Class1 is only being used in one of those calls. Any help on how to structure my classes or setup EF correctly would be greatly appreciated!
The problem is that you are using TPH (Table Per Hieararchy) that is a way that EF uses to implement inherithance. Using TPH EF needs a column named discriminator to associate the record with a specific entity of the hierarchy.
In your case I think you need TPT (but it depends on what you want access to classes). To do it just set the name of the Class2 table (or view) using ToTable. Otherwise you can add Discriminator column but you should leave EF to handle it.
I have a "base" entity with some properties that's being used by a bunch of other stuff (repository patterns, queues, etc) in some shared libraries. Mapped to a pluralized table.
I need to add a property to it for my specific implementation, and I want to reuse all the rest of the normal behaviors.
I derive a class:
public interface IItem {
[Key]
Guid Id { get; set; }
string Name { get; set; }
}
public class Item : IItem {
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
}
public interface IExtended {
bool IsExtended { get; set; }
}
[Table("Items")] // <-- my nemesis
public class ExtendedItem : Item, IExtended {
[Column("_Extended")]
public bool IsExtended { get; set; }
}
I set up the code-first context:
public class MyContext : DbContext {
public MyContext(string connectionString) : base(connectionString) {
// manually creating the tables, no migrations
Database.SetInitializer<EfQueueContext>(null);
}
public DbSet<Item> Items { get; set; }
}
Without DataAnnotation [Table] I get exception "Invalid column name 'Discriminator'" -- okay, weird but makes sense
With [NotMapped] I get exception "The entity type ExtendedItem is not part of the model for the current context" -- okay, makes sense
With annotation [Table("Item"] I get exception "table 'dbo.Item' doesn't exist" -- okay, duh forgot it pluralized original
With annotation [Table("Items")] I get exception "table 'dbo.Items1' doesn't exist" -- what??? where did the 1 suffix come from?
Even creating a brand-new DbContext that only refers to ExtendedItem and not Item still adds the '1' (update - I didn't actually create a clean instance; see comment on answer)
The problem is EF deduce you want to create a Table per Type (TPT) when you apply the Table atribute on the subclasses to specify the mapped table name. In your case you are trying to rename the table related with theExtendedItem entity, but you are using the same name of the root table, that's way EF is creating two tables one called Items1 (because you already use the Items name in the inheriting entity) related to the Item entity and another called Items related to the ExtentedItem entity
If you want to create a Table per Hierarchy (TPH) and you want to rename the root table, then you need to apply the [Table("Items")] data annotation on the root entity (Item) and all entities that inherit from it.
I'm using EF5 to produce a model from an existing DB structure. I map Insert/Update/Delete Stored Procedures to the entities. This is working fine.
What I would like to do next is pass a UserId to these SPs as a parameter but not have the UserId as a column within the underlying table (the SPs will utilize this parameter). I have lots of entities. Is it possible to somehow add a property that will always be added back in even after updating the model from the DB?
Many Thanks
If you are using EDMX to generate the Entity Framework object model, your classes are partial and you can add properties to the partial classes of your entities which will survive database regeneration.
If you have a ParticularEntity table in the DB and referenced in the EDMX, you may add a partial class file ParticularEntity.Augments.cs (the name is for your reference, and you can have multiples as normal with partial classes) to your project and within it
public partial class ParticularEntity
{
public string UserId { get; set; }
public void DoSomething(string userId)
{
someFunctionThatYouWantToNotBeAnExtension();
}
}
Alternatively, you could write a set of extension methods which your maps utilize. I don't think that's as clean as extending the EF classes with partials, though.
Entity created by EF are partial class so you can extend that class with your custom properties
YourEntity.cs //created by EF
public partial class YourEntity
{
public string Name { get; set; }
...
}
YourEntityExtended.cs // created by you
public partial class YourEntity
{
public int Id { get; set; }
}
I would like to mention that i am new to EF.
I am creating the Data Access library with EF 4.1.
For each Entity I have two tables for translation target.
ex : Events ==> Event_ar for Arabic and Event_en for English.
First Problem : I have an error if i write two DbSets of same Entity Type
so I did this work around which is absolutely not nice :
public class Event_en : Event { }
public class Event_ar : Event { }
public class DB : DbContext
{
public DbSet<Event_ar> Events_ar { get; set; }
public DbSet<Event_en> Events_en { get; set; }
}
I would like to know if there is a solution for it?
Second one
The Entity should be same name as a table, otherwise i have an error.
Ex : "dbo.Event_ar" should have a POCO "Event_ar"
It should be the name of the property that has the same name of the table.
Here : dbo.Events_ar ==> POCO "Events_ar"
Why I can't manipulate the names? Any solution?
I'm not sure if your solution is going in the right direction. It doesn't feel right to have a table for every language - you could simply add another column to the event table that specifies what the language is?
The you could use this column to retrieve the row with the desired language.
About tables and POCO entity names, you can override the table the entity is mapped to either through the use of a System.ComponentModel.TableAttribute at the class elvel, but to maintain POCO-ness I like to use EntityTypeConfiguration classes and specify the table name.
for example:
public class CurrencyConfiguration : EntityTypeConfiguration<Currency>
{
public CurrencyConfiguration()
{
this.ToTable("Conv", "Ref");
}
}
Then you add it to the model builder in the OnModelCreating override method on the DbContext.
public class MyContext : DbContext
{
public DbSet<Currency> Currencies { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new CurrencyConfiguration());
}
}