Entity Framework 4 code-only reference column name - entity-framework

I created classes:
public class Country
{
public long CountryId {get;set;}
public string CountryName {get;set;}
}
public class Profile
{
public long ProfileId {get;set;}
public string ProfileName {get;set;}
public Country Country {get;set;}
}
and configuration for Profile:
public class ProfileConfiguration : EntityConfiguration<Profile>
{
public IlluminatiCoreProfileConfiguration()
{
Relation(p => p.Country);
}
}
Then I create context and run context.CreateDatabase(). New database contains table Profiles with column Country_CountryId. How can I write configuration for changing column name to "CountryId"?
Thanks.

In your POCO for Profile:
public class Profile
{
public long ProfileId {get;set;}
public string ProfileName {get;set;}
[ForeignKey("CountryId")]
public Country Country {get;set;}
}
In your POCO for Country
[Table("Country")]
public class Country
{
[Column(Name = "CountryId")]
public int CountryId {get;set;}
}
This will over write the brain dead Object_Property mapping that EF by default creates. You can specify this on any table / property to override the actual DB column naming conventions.
EDIT:
I guess the namespace for those annotations would be helpful:
using System.ComponentModel.DataAnnotations;

Related

EF Core navigation property without relations(foreign-key)

I have three classes
public class Country
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte CountryID { get; set; }
public byte OfficialLangID { get; set; }
}
public class Language
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte LangID { get; set; }
}
public class Name
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public byte NameID { get; set; }
public bool isLanguage { get; set; } // true for language - false for country
public byte FK { get; set; } // FK=LangID or CountryID
}
Now I want to create Navigation properties:
Country.Name
Language.Name
Name.Language
Name.Country
I want to do it in this way for many reasons, one of them to search for all the names in one table without joining.
Please don't suggest another way,I want navigation properties for my way.
why you're doing it like this? putting a boolean field to check the type of the entity here doesn't make any sense? in the end, the ef framework will create 2 tables.
here is my approach:
public class Country
{
public byte Id {get;set;}
public string Name {get;set;}
public int LanguageId {get;set;}
}
public class Language
{
public byte Id {get;set;}
public string Name {get;set;}
// assuming that each language may have one or many countries
public ICollection<Country> Countries {get;set;}
}
ef core here will create the tables and the relations automatically. now if you see some code duplications (like I've understood), that the 2 entities use the same field types and names, here is what you can do
public abstract class EntityBase
{
public byte Id {get;set;}
public string Name {get;set;}
}
now inherit this abstract class to the entity class
public class Country : EntityBase
{
public int LanguageId {get;set;}
}
public class Language : EntityBase
{
public ICollection<Country> Countries {get;set;}
}

Foriegn Key from multiple tables on a single column EF code First

I am using EF version 6.1 and have a mapping problem:
class BasePoco
{
public Guid Id{get;set;}
}
class Student : BasePoco
{
public string Name;
}
public class UserBase : BasePoco
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public string Photo { get; set; }
}
public class UserDetail : UserBase
{
public string MobileNumber { get; set; }
public string EmailID { get; set; }
}
public Enum UserType
{
Student = 1,
User=2
}
the Attendance class
public class Attendance
{
public class UserId {get;set;} // Can be either student or user
public UserType UserType {get;set;}
}
I need to mark attendance for Student as well as User in the same table.
The UserType would determine whether the Id is of a student or User and the primary key would be a combination of UserType and Id.
How can I accomplish this using EF code first approach.
Sorry you cant use multiple type over single property. You do understand, because EF run over metadata. Which use EF know metadata from model class. This is a problem. Attendance table foregin key is multiple table referance and Attendance model contains both model. You should create logical layer for check UserType and access correct model. For example
public class Attendance
{
public UserType userType {get;set;}
public Guid? UserId {get;set;}
public virtual User user {get;set;}
public Guid? StudentId {get;set;}
public virtual Student student {get;set;}
}
now layer class
public class AttendanceUserLayer
{
public static object GetUser(Attendance attendance) {
if (attendance.userType == UserType.User) {
return attendance.User;
} else {
return attendance.Student;
}
}
how to use
Attendance attendance = context.Attendance.FirstOrDefault();
var userOrStudent = AttendanceUserLayer.GetUser(attendance);
if you cannot use the type of object result, write interface both class and set return type that interface.

Entity Framework - Eager loading, all properties to list

I have a simple project in which i have the following model.
Customer 1--->N Addresses N<----1 City N<----1 Country
^
N|
|
AddressTypes 1-------+
Here is my code:
public partial class Customer {
public Customer() {
this.Address = new HashSet<Address>();
}
public int Id {get;set;}
public string FirstName {get;set;}
public string LastName {get;set;}
public System.DateTime Birthday {get;set;}
public virtual ICollection<Address> Address {get;set;}
}
public partial class Address {
public int Id {get;set;}
public string Street {get;set;}
public string Area {get;set;}
public string Post {get;set;}
public bool isDeleted {get;set;}
public virtual Customer Customer {get;set;}
public virtual City City {get;set;}
public virtual AddressType AddressType {get;set;}
}
public partial class AddressType {
public AddressType() {
this.Address = new HashSet<Address>();
}
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Address> Address {get;set;}
}
public partial class Country {
public Country() {
this.City = new HashSet<City>();
}
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<City> City {get;set;}
}
public partial class City {
public City() {
this.Address = new HashSet<Address>();
}
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Address> Address {get;set;}
public virtual Country Country {get;set;}
}
public partial class MyModelContext : DbContext {
public MyModelContext()
: base("name=MyModelContext") {
this.Configuration.LazyLoadingEnabled = true;
this.Configuration.ProxyCreationEnabled = false;
}
public virtual DbSet<Country> Countries {get;set;}
public virtual DbSet<City> Cities {get;set;}
public virtual DbSet<AddressType> AddressTypes {get;set;}
public virtual DbSet<Address> Addresses {get;set;}
public virtual DbSet<Customer> Customers {get;set;}
}
I want to return a list of customers. At first i tried to do a simple Customers.ToList() but i was getting an exception during serialization and i read that this was caused by cyclical references. So i added
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = false;
and then i was able to get the customers but without the addresses. I tried doing:
public List<Customer> getCustomers() {
MyModelContext db = new MyModelContext();
return db.Customers.Include("Address").ToList();
}
but i don't know how to retrieve ALL the properties. I want to get in the list every customer and his addresses including the city, country, addresstype of each address. How can i do it?
You have couple of options:
1. Use DTOs (Data Transfer Objects).
2. Explicitly ignore the problematic property that contains the circular references to the parent object by applying the below Attributes:
// in Address entity
[IgnoreDataMember]
[XmlIgnore]
[NonSerialized]
public Customer Custom { get; set; }
Also in AddressType.Address, City.Address, and Country.City.
3. Project your entities into anonymous objects and exclude the pr:
db.Customers.Select(c => new
{
c.Id,
c.FirstName,
c.LastName,
c.Birthday,
Address = c.Address.Select<Address, object>(a => new
{
a.Id,
AddressType = new
{
a.AddressType.Id,
a.AddressType.Name
},
a.Area,
City = new
{
a.City.Id,
Country = new
{
a.City.Country.Id,
a.City.Country.Name
},
a.City.Name,
},
a.Post,
a.Street,
a.isDeleted
}),
});
You'll have to turn LazyLoadingEnabled and ProxyCreationEnabled back on in order for it to work (or use Include).
(As a side note, i don't really understand why you need this circular references at all, what benefit do you get from AddressType.Address?)
I solved it this way:
public List<Customer> getCustomers() {
var customers = db.CustomerSet.Include("Address")
.Include("Address.AddressType")
.Include("Address.City")
.Include("Address.City.Country")
.ToList();
return customers;
}
i don't really like that i have to explicitly write all the properties of the customer and there is not a generic way of doing what i want but it works.

Eager loading failing for Child Collection in EF 4.3.1

I have the following classes:
public class Configuration
{
public long Id {get;set;}
public string Name {get;set;}
public Expression Criteria {get;set;}
}
public class Expression
{
public long Id {get;set;}
public string Value {get;set;}
public ICollection<Parameter> Parameters {get;set;}
}
public class Parameter
{
public long Id {get;set;}
public MyType Type {get;set;}
}
public class MyType
{
public long Id {get;set;}
public string Name {get;set;}
}
I am trying to eagerly load the entire configuration object using:
dbContext.Configurations.Select(i => i.Criteria).Include(i => i.Parameters.Select(j => j.Type)).ToList()
I am however getting null for the Parameters property and it is not getting fetched.
What am I doing wrong.
Try this:
dbContext.Configurations.Select(i => i.Criteria).Include("Parameters").Include("Parameters.Type").ToList()

With entity framework, how do I force a sql datatype for my string member

I have a product class, for which the ManufacturerNumber gets generated as nvarchar(max) - how would I go about forcing the code-first framework to make it nvarchar(255)
public class Product : BaseEntity
{
public string ManufacturerNumber { get; set; }
}
Decorate the property with StringLength attribute.
public class Product : BaseEntity
{
[StringLength(255)]
public string ManufacturerNumber { get; set; }
}