Foreign Key without ugly blablaId - entity-framework

Is it possible to do foreign key without blablaId?
I mean next situation
public class Blog
{
public int BlogId { get; set; }
public string Name { get; set; }
public virtual List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; } // Why should I have this ugly property?
public virtual Blog Blog { get; set; }
}
My models are core project. But I should play EF rules. It means core project depend on DAL project.

It's not required declare the FK property in your entity. If you delete it, EF will create it for you in your DB.
However, imagine if the Blog is not in memory, this would require you to first execute a query on the database to retrieve that Blog so that you can set the property. There are times when you may not have the object in memory, but you do have access to that object’s key value. With a foreign key property, you can simply use the key value without depending on having that instance in memory:
currentPost.BlogId=2;

Related

Advanced TPH Mapping to Legacy Database

I have been working on a project in which I am trying to mold entity framework to an existing FoxPro 2.x database in order to use the data while leaving the tables readable to a legacy application (more details on my previous question).
I've had pretty good luck configuring the DBContext to the physical data tables and I have most of my mapping set up. The legacy data structure has a Bills table with a unique primary Id key, but all the LineItems that can be posted to a bill are stored in a single Charges table without a simple primary key.
My question pertains to discriminator mapping in code-first EF. I am recreating the table as TPH in my data objects, so I have
public abstract class Posting
{
public System.DateTime? Post_Date { get; set; }
public string Bill_Num { get; set; }
public string Type { get; set; }
public string Pcode { get; set; }
public string Pdesc { get; set; }
public decimal? Custid { get; set; }
public string Createby { get; set; }
public System.DateTime? Createdt { get; set; }
public string Createtm { get; set; }
public string Modifyby { get; set; }
public System.DateTime? Modifydt { get; set; }
public string Modifytm { get; set; }
public string Linenote { get; set; }
public decimal? Version { get; set; }
public string Id { get; set; }
public string Batch { get; set; }
public virtual Billing Bill { get; set; }
}
public abstract class Charge : Posting
{
}
public class ServiceLine : Charge
{
public string Chargeid { get; set; }
public virtual ICollection<Payment> Payments { get; set; }
}
public class ChargeVoid : Charge
{
}
public abstract class Payment : Posting
{
}
public class PaymentLine : Payment
{
public string Postid { get; set; }
public string Svc_Code { get; set; }
public string Name { get; set; }
public string Checkno { get; set; }
public System.DateTime? Checkdate { get; set; }
}
public class PaymentVoid : Payment
{
}
where my mapping strategy so far is along these lines:
public class PostingMap : EntityTypeConfiguration<Posting>
{
public PostingMap()
{
// Primary Key
this.HasKey(t => new {t.Bill_Num, t.Post_Date, t.Pcode});
this.Map<Charge>(m => m.Requires("Type").HasValue("C"))
.ToTable("Charges");
this.Map<Payment>(m => m.Requires("Type").HasValue("P"))
.ToTable("Charges");
}
}
I have omitted some fields and mapping classes, but this is the core of it.
Every record has the C/P classification, so this makes everything in the table either a Charge or a Payment.
Every Posting is associated with a Bill via Bill_Num foreign key.
The ServiceLine object is only distinct from ChargeVoid objects (which are adjustment entries and no-value information entries associated with a bill) by having values for Pcode and Chargeid (which is just Bill_Num tagged with 01++). I have no idea how to model this.
It is very similar for the Payment hierarchy as well.
So with my current setup, I have Postings which doesn't have a unique key, Charges which has a subset of ServiceLines with values for Chargeid and Pcode and a subset with nulls, and Payments similar to Charges. PaymentLines are also many-to-one with ServiceLines by way of Pcode while PaymentVoids have Pcode = null.
Is there a way I can assign this complex mapping since I can't simply discriminate on !null? On top of that, will EF handle the key assignments once I get the inheritance set up, or am I going to have issues there as well?
Also, if there is a better way to break this object inheritance down, I am all ears.

DBContext simplest way to update foreign key

var orgAcc = db_.Accounts.Find(account.Id);
db_.Entry(orgAcc).CurrentValues.SetValues(account);
orgAcc.Company = db_.Companys.Find(account.Company.Id);
db_.SaveChanges();
Is this the simplest way to update an entity's association ?
public class ChartofAccount: MasterData
{
[Key]
public int Id { get; set; }
[Required]
[StringLength(6)]
public string Code { get; set; }
public virtual Company Company { get; set; }
[Required]
public string AccountName { get; set; }
[Required]
[StringLength(3)]
public string AccountCurrency { get; set; }
public virtual AccountCatagory Category1 { get; set; }
public virtual AccountCatagory Category2 { get; set; }
public string Reference { get; set; }
public bool HasTransaction { get; set; }
}
The way SetValues works is to do a property-by-property compare, and for each property from the left-hand object that is also in the argument, that has a matching type, it will update the left-hand object with the value from the argument.
I presume account.Company is a different type of object to orgAcc.Company, such as something that has come in from an MVC controller argument (ie account and it's referenced objects are not EF entities). In this case your approach seems a sound way of doing it.
That being said, orgAcc probably has a Company property, and a CompanyId property, in order to support the EF relationships, so, if your account object followed the same pattern, ie storing a CompanyId field directly, rather than having to navigate through the company, then SetValues could automatically update the CompanyId field, which should update the foreign key when you save changes. This way you could also avoid the step that specifically assigns the orgAcc.Company field.

Entity Framework Code First Migration manually removed column causing issue with migration

I have a Blog object that has an Admin object. I initially had this setup wrong and it created my columns incorrectly. I manually removed the "Admin_Id" foreign key field and relationship. Now when I run the migration again, it doesn't add the foreign key and relationship back.
Can I force the entity framework somehow to update the database again?
My objects:
Admin
public class Admin: WebPage, IWebPage
{
public string Name { get; set; }
public string Email { get; set; }
public string About { get; set; }
public string Image { get; set; }
public List<Blog> Blogs { get; set; }
}
Blog
public class Blog : WebPage, IWebPage
{
public string Title { get; set; }
public string Summary { get; set; }
public string ArticleBody { get; set; }
public string Author { get; set; }
public DateTime PostingDate { get; set; }
public virtual Admin Admin { get; set; }
public virtual BlogCategory BlogCategory { get; set; }
public virtual List<Comment> Comments { get; set; }
}
The Entity Framework stores the migrations that have been applied to the database in the __MigrationHistory table. If you delete the row in this table representing a particular migration (the MigrationId column contains the name of the migration class), that migration will be reapplied the next time you do an update-database.
That said, this will cause the entire migration to be reapplied, not just the parts of it that happen to be missing in the database, including all table creations, drops, etc., etc., so use it with care if you haven't previously manually backed out the changes that that migration has put in place, as some of those operations can and will cause errors if the database objects already exist.

code first relationships with multiple foreign keys

I have a scenario I'm getting a little muddled with using EF code first. The classes I've created are below:
public class Company
{
public int Id { get; set; }
public List<Contact> Contacts { get; set; }
public List<Job> Jobs { get; set; }
}
public class Contact
{
public int Id { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
public int CompanyId { get; set; }
public List<Job> Jobs { get; set; }
}
public class Job
{
public int Id { get; set; }
[ForeignKey("CompanyContactId")]
public virtual CompanyContact CompanyContact { get; set; }
public int CompanyContactId { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
public int CompanyId { get; set; }
}
However, when I build the DB I get the following error:
Introducing FOREIGN KEY constraint 'FK_Contacts_Company_CompanyId' on table 'Contacts' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
So a little research indicates the answer to this is to use the Fluent API to define the mappings as required but I can't get my head around how to do this or find an example of a similar scenario.
I realise I could remove the Company class from Job and navigate through Contact but I'd prefer not to if possible.
Any help gratefully received
You want to use the EF model builder to set up these relationships.
An example of how you would do this for one of your properties would be the following:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Contact>().HasOptional(e => e.Company).WithMany(c=>c.Contacts);
}
For more of an explanation around how to use the modelbuilder take a look at my article on EF Navigation Properties

EF CTP4: For Code Only, no database generation needed, how much DB info is needed?

I have a database, and I have entity POCO's, and all I want to use EF for is to map between the two and keep track of changes for loading, saving, etc.
I have been reading a lot of the literature (such as it is) on "Code First", and I am unclear on how much of the database information I need to supply when there is not going to be a database generated.
For example, does EF need to know which properties are keys, the maximum length of string properties, the relationships between the tables, etc.? Or if it does need to know, can it get that information from the database itself? In other words, do I have to provide [Key] annotations and such, or provide configuration information detailing the foreign-key relationships, if no database needs to be created?
UPDATE: To make things a little clearer, the following code is what I am talking about. I have to manually create this class derived from DbContext. I could supply a lot of DB information about the properties in OnModelCreating, or in attributes attached to the properties in the entity classes.
public class SchedulerContext : DbContext
{
public SchedulerContext(EntityConnection connection)
: base(connection)
{
}
public DbSet<Client> Clients { get; set; }
public DbSet<ConsultantDistrict> ConsultantDistricts { get; set; }
public DbSet<ConsultantInterviewSetting> ConsultantInterviewSettings { get; set; }
public DbSet<ConsultantUnavailable> ConsultantsUnavailable { get; set; }
public DbSet<CustomEmailTemplate> CustomEmailTemplates { get; set; }
public DbSet<DateEvent> DateEvents { get; set; }
public DbSet<Event> Events { get; set; }
public DbSet<EventItem> EventItems { get; set; }
public DbSet<EventItemUserViewed> EventItemsUserViewed { get; set; }
public DbSet<FlaggedDate> FlaggedDates { get; set; }
public DbSet<Interview> Interviews { get; set; }
public DbSet<Interviewee> Interviewees { get; set; }
public DbSet<IntervieweeNote> IntervieweeNotes { get; set; }
public DbSet<InterviewEvent> InterviewEvents { get; set; }
public DbSet<NotificationSent> NotificationsSent { get; set; }
public DbSet<SchedulerRole> SchedulerRoles { get; set; }
public DbSet<SiteEvent> SiteEvents { get; set; }
public DbSet<UnavailableHour> UnavailableHours { get; set; }
public DbSet<UserLogin> UserLogins { get; set; }
public DbSet<UserSites> UserSites { get; set; }
public DbSet<Visit> Visits { get; set; }
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ConsultantUnavailable>().MapSingleType().ToTable("ConsultantsUnavailable");
modelBuilder.Entity<EventItemUserViewed>().MapSingleType().ToTable("EventItemsUserViewed");
}
}
Yes, the EF does need information on string field lengths, foreign keys, etc., in the model. For example, if a DB FK has a cascade, the EF needs to know that so that it doesn't force you to manually delete detail records; if the EF is aware of the cascade it will let the DB handle that. Similarly, if the EF is aware that a key is store-generated (e.g., auto-incremented), it won't complain when you don't set it on a new record, because it will presume that the DB will do that.
However, the code-only approach takes a "convention over configuration" approach. You don't have to specify values which the EF can guess. You can read about those here.
If you are doing Code Only, the EF doesn't look at the DB at all when creating the model.
There is no way to tell the EF to look at code and the DB to create the model. You have to choose one or the other.