2

I am trying to create a composite key with all FKs. For uniqueness I need 4 properties. I've added two, but the third FK and fourth FK throw errors since they are from the same table and I am not sure how to set that up?

I've read many answers and I am just not seeing how to write it out. I am working on an ASP.Net MVC web app with Entity Framework and I've looked into these:

https://www.entityframeworktutorial.net/code-first/foreignkey-dataannotations-attribute-in-code-first.aspx

https://www.entityframeworktutorial.net/code-first/inverseproperty-dataannotations-attribute-in-code-first.aspx

Defining multiple Foreign Key for the Same table in Entity Framework Code First

Entity Framework Code First - two Foreign Keys from same table

https://forums.asp.net/t/2135907.aspx?Multiple+Relationships+Foreign+Keys+Between+Two+Tables+in+Classes+

https://febdev.wordpress.com/2013/01/30/entity-framework-mapping-references-with-composite-keys/

Entity Framework Code First One to One relationship on composite key

One problem is that I never worked with modelbuilder, so an answer I got from another site was just links, but that didn't help me much.

public class TradeJournal
{
    [Key, Column(Order = 0)]
    public int UserID { get; set; }
    [ForeignKey("UserID")]
    public UserAccount UserAccount { get; set; }

    [Key, Column(Order = 1)]
    public int AccountNumber { get; set; }
    [ForeignKey("AccountNumber")]
    public FxAccount FxAccount { get; set; }

    [Key, Column(Order = 2)]
    [ForeignKey("OpenTime")]
    public string OpenTime { get; set; }
    public HistoricalTrade Open { get; set; }

    [Key, Column(Order = 3)]
    [ForeignKey("CloseTime")]
    public string CloseTime { get; set; }
    public HistoricalTrade Close { get; set; }
}

public class HistoricalTrade
{
    [Key, Column(Order = 0)]
    public int UserID { get; set; }
    [ForeignKey("UserID")]
    public UserAccount UserAccount { get; set; }

    [Key, Column(Order = 1)]
    public int AccountNumber { get; set; }
    [ForeignKey("AccountNumber")]
    public FxAccount FxAccount { get; set; }

    [Key, Column(Order = 2)]
    [JsonProperty("openTime")]
    public string OpenTime { get; set; }

    [Key, Column(Order = 3)]
    [JsonProperty("closeTime")]
    public string CloseTime { get; set; }
}

The database migration has thrown the above error, or the "OpenTime is not a valid entity. (something like) A key must be a valid entity with a non-abstract getter and setter.

I need the key to be the four properties specified. Thanks.

Edit: I've moved "ForeignKey("OpenTime") and "CloseTime" above the reference property, and the full error I've mentioned comes to play from the title, which is :

One or more validation errors were detected during model generation:

TradeJournal_Close_Target_TradeJournal_Close_Source: : The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical.

EDIT: I tried my hand at fluent API as suggested and I run into a new error : "SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint. This occurred on db.SaveChanges(); My attempt at Fluent API is this:

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<TradeJournal>()
               .HasKey(k => new { k.UserID})
               .HasRequired(r => r.User);

            modelBuilder.Entity<TradeJournal>()
               .HasKey(k => new { k.AccountNumber })
               .HasRequired(r => r.Account);

            modelBuilder.Entity<TradeJournal>()
              .HasKey(k => new { k.OpenTime })
              .HasRequired(r => r.Open);

            modelBuilder.Entity<TradeJournal>()
              .HasKey(k => new { k.CloseTime })
              .HasRequired(r => r.Close);
        }
  • Just for records sake, one of my links posted might answer my question and I just don't understand how to implement? – JuniorExtreme May 02 '19 at 13:19
  • If you are receiving an error message, please show us the exact error message. – ESG May 02 '19 at 13:58
  • @ESG This is the current one : "The property 'OpenTime' cannot be configured as a navigation property. The property must be a valid entity type and the property should have a non-abstract getter and setter. For collection properties the type must implement ICollection where T is a valid entity type." This is the other one I mentioned. The original one was the title one that I don't have the full wording of currently. – JuniorExtreme May 02 '19 at 14:18
  • Can you share `OpenTime` class? – ilkerkaran May 02 '19 at 14:22
  • @ilkerkaran OpenTime is a property of HistoricalTrade, the third key. I am trying to reference a FK to that information in TOne. OpenTime comes from an API call that gives it the value. – JuniorExtreme May 02 '19 at 14:26
  • can you move `[ForeignKey("OpenTime")]` above the `public HistoricalTrade Close { get; set; }` line ? and you can find more info about `ForeignKey` attribute https://www.entityframeworktutorial.net/code-first/foreignkey-dataannotations-attribute-in-code-first.aspx – ilkerkaran May 02 '19 at 14:34
  • @ilkerkaran So I've tried that, which puts the error on CloseTime. If I do it to both, this is the error (the one mentioned in the title, so I have it now lol) : "One or more validation errors were detected during model generation: TradeJournal_Close_Target_TradeJournal_Close_Source: : The number of properties in the Dependent and Principal Roles in a relationship constraint must be identical." – JuniorExtreme May 02 '19 at 14:39
  • I think you miss some keys to match. You need to match `HistoricalTrade.AccountNumber` (the one with the Key attribute) to a FK property in `TradeJournal`. By the way, if I were you, I would definitely use fluent API. – ilkerkaran May 02 '19 at 14:43
  • @ilkerkaran So I changed the reference to HistoricalTrade instead of FxAccount and named it Account. Now all three of them come up as the error. I will give Fluent API another go and see if I can understand it and implement it today. There was an issue I had last time, getting it to work with FKs while being a one to one. – JuniorExtreme May 02 '19 at 14:55
  • @JuniorExtreme **composite key** is the keyword to your problem. I believe https://stackoverflow.com/questions/47394333/ef-composite-key-fluent-api-with-foreign-key?rq=1 will solve your problem – ilkerkaran May 02 '19 at 14:57
  • @ilkerkaran So I ran into a new error. I tried my hand at Fluent API, and am about to edit the question to show what I have and the new error that pops up. – JuniorExtreme May 03 '19 at 00:38
  • @JuniorExtreme I think you miss the point of `HasKey`, It means That preoperty is the key of that object. Translate into db, that column is the primary key. If you got composite key you should go like this; `.HasKey(k => new { k.UserID,k.AccountNumber,k.OpenTime, k.CloseTime})` thats how ef will now that object has a composite key – ilkerkaran May 03 '19 at 06:34

0 Answers0