Configuring many One-To-One relationships with Entity Framework Code First and Fluent API

送分小仙女□ 提交于 2020-01-04 05:28:08

问题


I have a horrible database model (in MySQL though I don't think that matters) that someone else designed so I'm stuck with it, but want to use with Entity Framework with it anyway:

Database

Item

ASSET_ID*   ASSET_NAME  FIELDS_ID
1          Cat         1
2          Dog         2
3          Fish        3

ItemFields

ID*    CUSTOMFIELD1ID    CUSTOMFIELD2ID    CUSTOMFIELD3ID
1     1001              1002              1003
2     1004              1005              1006
3     1007              1008              1009

Field

ID*    STRINGVAL
1001   Meow Mix
1002   House
1003   5lbs
1004   Kibble
1005   Yard
1006   30lbs
1007   Fish Food
1008   Tank
1009   0.5 ounces

*indicates table's PK


Goal

Ultimately, I'm trying to configure the relationships so I can get custom data like this:

Item item = GetItem(1);
item.Food.ToString(); // Output: meow mix
item.Place.ToString(); // Output: house
item.Weight.ToString(); // Output: 5 lbs 

...etc. but honestly I'd settle for this at this point:

Item item = GetItem(1);
Item.ItemFields.CustomField3.Value // Output: 5 lbs
Item item = GetItem(2);
Item.ItemFields.CustomField2.Value // Output: Yard
Item item = GetItem(3);
Item.ItemFields.CustomField1.Value // Output: Fish Food


Solution thus far

So far I've got this:

One-To-One: Item - ItemFields

modelBuilder.Entity<Item>()
    .HasRequired(x => x.ItemFields)
    .WithRequiredPrincipal(y => y.Item);

But what about mapping ItemFields.CustomField1ID to Field.ID?

Is it even possible to configure a relationship like this using EF code first? I'm pretty confused about whether or not this is a one-to-one or a one-to-many... I think what it actually is is many one-to-ones (if that makes sense).

Any suggestions?


回答1:


I may have figured this out. I edited my ItemFields class to look like this:

public class ItemFields
{
    public int Id { get; set; }
    public int CUSTOMFIELD1ID { get; set; }
    public virtual Field CustomField1 { get; set; }

And then configured these relationships:

modelBuilder.Entity<Item>()
    .HasRequired(x => x.CustomField1)
    .WithMany()
    .HasForeignKey(x => x.CUSTOMFIELD01_ID);
modelBuilder.Entity<Item>()
    .HasRequired(x => x.CustomField2)
    .WithMany()
    .HasForeignKey(x => x.CUSTOMFIELD02_ID);

And it seems to have worked, though to be honest I don't fully understand why. I'd still ideally like to map them to more user-friendly classes.




回答2:


I think you agree that at this case we actually have one-to-many relationship: one item has several fields and table ItemFields is surrogate thing. I recommend you to perform refactoring and create only two tables: Items and Fields. In Fields table will be added column Type - similar CUSTOMFIELD1ID(2ID,3ID) and foreign key referenced directly to Items table. In Item class were added properties: Food, Place and Weight. They will not be mapped to columns, but you can use them as you specified in your question for accessing to particular fields(look at IMPLEMENTATION section):

MODELS:

public enum CustomType
{
    Food,
    Place,
    Weight
}

public class Item
{
    public int ID { get; set; }
    public string ASSET_NAME { get; set; }
    public virtual ICollection<Field> fields { get; set; }

    [NotMapped]
    public Field Food { get { return fields == null ? null : fields.Where(x => x.Type == CustomType.Food).FirstOrDefault(); } }
    [NotMapped]
    public Field Place { get { return fields == null ? null : fields.Where(x => x.Type == CustomType.Place).FirstOrDefault(); } }
    [NotMapped]
    public Field Weight { get { return fields == null ? null : fields.Where(x => x.Type == CustomType.Weight).FirstOrDefault(); } }
}

public class Field
{        
    public int ID { get; set; }
    public string STRINGVAL { get; set; }
    public CustomType Type { get; set; }

    public virtual Item Item { get; set; }
}

TABLES:

IMPLEMENTATION:

var db = new DataContext();
var item = db.Items.Include("fields").Where(x => x.ID == 1).First();
var Food = item.Food;
var Place = item.Place;
var Weight = item.Weight;


来源:https://stackoverflow.com/questions/35639341/configuring-many-one-to-one-relationships-with-entity-framework-code-first-and-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!