How not persist property EF4 code first? - c#

How do I make non persisted properties using codefirst EF4?
MS says there is a StoreIgnore Attribute, but I cannot find it.
http://blogs.msdn.com/b/efdesign/archive/2010/03/30/data-annotations-in-the-entity-framework-and-code-first.aspx
Is there a way to set this up using EntityConfiguration?

In EF Code-First CTP5, you can use the [NotMapped] annotation.
using System.ComponentModel.DataAnnotations;
public class Song
{
public int Id { get; set; }
public string Title { get; set; }
[NotMapped]
public int Track { get; set; }

Currently, I know of two ways to do it.
Add the 'dynamic' keyword to the property, which stops the mapper persisting it:
private Gender gender;
public dynamic Gender
{
get { return gender; }
set { gender = value; }
}
Override OnModelCreating in DBContext and remap the whole type, omitting the properties you don't want to persist:
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Person>().MapSingleType(p => new { p.FirstName, ... });
}
Using method 2, if the EF team introduce Ignore, you will be able to easily change the code to:
modelBuilder.Entity<Person>().Property(p => p.IgnoreThis).Ignore();

If you don't want to use Annotations, you can use the Fluent API. Override the OnModelCreating and use DbModelBuilder's Ignore() method. Supposing you have a 'Song' entity:
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Song>().Ignore(p => p.PropToIgnore);
}
}
You can also use EntityTypeConfiguration to move configurations to separate classes for better manageability:
public class MyContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new SongConfiguration());
}
}
public class SongConfiguration : EntityTypeConfiguration<Song>
{
public SongConfiguration()
{
Ignore(p => p.PropToIgnore);
}
}

I'm not sure if this is available yet.
On this MSDN page the Ignore Attribute and API are described but below, in the comments, somebody writes on 4 june 2010:
You will be able to ignore properties in the next Code First release,

Add
using System.ComponentModel.DataAnnotations.Schema
to the model class. (Must include "SCHEMA")
Add [NotMapped] data annotation to the field(s) you want to keep from persisting (ie. not save to database).
This will prevent them from being added as a column to the table in the db.
Please note - previous answers may have included these bits, but they did not have the full "using" clause. They merely left off "schema" - under which the NotMapped attribute is defined.

Related

Entity Framework - Create Composite PK from value object

How can i create a composite primary key in parent using fields in a valueobject ?
The valueobject will not have an own table in the database, i want these two props to be inserted into the parents table.
ie.
Entities
public class Parent
{
public string Name { get;set; }
public MyValueObject MyValueObj { get;set; }
}
public class MyValueObject
{
public int Id { get;set; }
public int SSN { get;set; }
}
DbContext for parent
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>().Property(new { p.MyValueObj.Id, p.MyValueObj.SSN}).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
base.OnModelCreating(modelBuilder);
}
I want the Parent table to look like this:
Composite PK
-----------
Id SSN Name
1 000000 Mikael
If you can use inheritance then it should look like this:
public class Parent : MyValueObject
{
public string Name { get;set; }
}
public class MyValueObject
{
public int Id { get;set; }
public int SSN { get;set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>().Property(new { p.Id, p.SSN}).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
base.OnModelCreating(modelBuilder);
}
The reason why your implementation won't work is pretty simple - Entity Framework just can't transform your complex object (which is set as property) to SQL field, so it will try to find it as a referenced object in other table. In the code I've provided you don't have any complex objects as a property, so EF will easily map all properties to SQL columns.
UPDATE
Actually, I did some more investigations and found an article stating that you can use complex types. I have never used this (and even seen) before, so can't describe you all sides of this question, but what I see from article is that this complex property can't be optional, so you will need always initialize that. Also I can only suppose, but probably you don't even need to mark all fields of that complex type as primary key, so you should have something just like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Parent>().Property(p => p.MyValueObj).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
base.OnModelCreating(modelBuilder);
}
Not sure if that will work, just give it a try :)

Entity Framework 6 Add Data Annotations on referenced class

Just wondering if it was possible to add Data Annotations to a class referenced from a class library which has no reference on EntityFramework.
For example Project.Data.Entities library
public class User {
public long Id { get; set; }
public string UserName { get; set; }
}
Project.Data.Repositories.EntityFramework references Project.Data.Entities library. How can I add the Data Annotations regarding Key properties, Column names, Table names, etc.?
There are fluent APIs for this purpose.
EDIT
About your mapping you have to override OnModelCreating
public class TestContext : DbContext
{
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>()
.ToTable("user")
.HasKey(_ => _.Id);
modelBuilder.Entity<User>()
.Property(_ => _.Id).HasColumnName("id");
modelBuilder.Entity<User>()
.Property(_ => _.UserName).HasColumnName("username"); // Add also HasMaxLength here
}
}
(if your database already exists and it's not created by EF on your model you need to disable also migrations)
EDIT
If you installed SQL Server with a CI codepage, column name casing is not important. So you need only to specify HasMaxLength

Entity Framework Code First table naming issue, singular confilcts with Plural

I have 2 table which I'm trying to access in MVC, one called Employees and one called Accountable. This is my code: -
public class dbEntity: DbContext
{
public dbEntity(): base("name=dbEntity") {}
public DbSet<Accountable> Accountable { get; set; }
public DbSet<Employees> Employees { get; set; }
}
The problem is the code complains that it can't find the table 'Accountables', I know I can add this line: -
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); }
But then the code complains that it can't find 'Employee'. At the moment it is not practical to rename the tables, is there another way around it?
Thanks
Add a data annotation of your table's name in the database to your context class.
[Table("TableName")]

Entity Framework Code First - How to ignore a column when saving

I have a class called Client mapped to a database table using Entity Framework code first. The table has a computed field that I need available in my Client class, but I understand that it won't be possible to write to this field. Is there a way of configuring Entity Framework to ignore the property when saving, but include the property when reading?
I have tried using the Ignore method in my configuration class, or using the [NotMapped] attribute, but these prevent the property from being read from the database.
You can use DatabaseGeneratedAttribute with DatabaseGeneratedOption.Computed option:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public ComputedPropertyType ComputedProperty { get; set; }
or if you prefer fluent api you can use HasDatabaseGeneratedOption method in your DbContext class:
public class EntitiesContext : DbContext
{
public DbSet<EntityType> Enities { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EntityType>().Property(e => e.ComputedProperty).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
}
}
Mark property as computed:
modelBuilder
.Entity<MyEntityType>()
.Property(_ => _.MyProperty)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);

EF 4.1 Code First POCOs Library

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());
}
}

Categories

Resources