Entity Framework 6 TPT and foreign keys
I'm stuck trying to get EF to work with foreign keys in a TPT scenario. I think it is complicated in that one table has a one to many relationship, and the other has a one to one relationship.
This code is boiled down to illustrate the problem (GitHub: https://github.com/Dash/EFTest for VS project).
When I create a foreign key in the base Persons table I get an error about the type not being matched:
Product: FromRole: NavigationProperty 'Product' is not valid. Type
'Buyer' of FromRole 'Product_Buyers_Target' in AssociationType
'Product_Buyers' must exactly match with the type 'Person' on which
this NavigationProperty is declared on.
To try and tackle this, I move the Product navigation property up to the children, but then I get an error due to the ProductId column not existing in the database - it is trying to look in the derived tables and not in the base table.
I'm not entirely clear how to resolve this problem and have been going around in circles and googling until my eyes bleed. Can anybody help?
Model
public abstract class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Product Product { get; set; }
}
public class Buyer : Person
{
public string ShipTo { get; set; }
}
public class Seller : Person
{
public int Rating { get; set; } = 0;
}
public class Product
{
public int Id { get; set; }
public string Description { get; set; }
public virtual Seller Seller { get; set; }
public virtual IList<Buyer> Buyers { get; set; }
}
Schema
public class ProductSchema : EntityTypeConfiguration<Product>
{
public ProductSchema()
{
HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Description)
.HasMaxLength(256);
HasOptional(p => p.Seller)
.WithRequired(i => i.Product)
.Map(m => m.MapKey("ProductId"));
HasMany(p => p.Buyers)
.WithRequired(i => i.Product)
.Map(m => m.MapKey("ProductId"));
}
}
public class PersonSchema : EntityTypeConfiguration<Person>
{
public PersonSchema()
{
ToTable("Persons");
HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Name)
.HasMaxLength(128);
}
}
public class SellerSchema : EntityTypeConfiguration<Seller>
{
public SellerSchema()
{
ToTable("Sellers");
HasKey(s => s.Id)
.Property(s => s.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(s => s.Rating);
}
}
public class BuyerSchema : EntityTypeConfiguration<Buyer>
{
public BuyerSchema()
{
ToTable("Buyers");
HasKey(b => b.Id)
.Property(b => b.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(b => b.ShipTo)
.HasMaxLength(256);
}
}
SQL
CREATE TABLE Products (
Id INT IDENTITY PRIMARY KEY,
[Description] nvarchar(256),
)
create table Persons (
Id int IDENTITY PRIMARY KEY,
[Name] nvarchar(128),
ProductId INT NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products(Id)
)
CREATE TABLE Buyers (
Id INT PRIMARY KEY,
ShipTo nvarchar(256)
)
CREATE TABLE Sellers (
Id INT PRIMARY KEY,
Rating INT NOT NULL DEFAULT 0
)
DECLARE @ProductId int;
INSERT INTO Products ([Description]) VALUES ('Widget');
SET @ProductId = @@IDENTITY;
INSERT INTO Persons ([Name], ProductId) VALUES ('Bob the seller', @ProductId);
INSERT INTO Sellers (Id, Rating) VALUES (@@IDENTITY, 0);
INSERT INTO Persons ([Name], ProductId) VALUES ('Bert the buyer', @ProductId);
INSERT INTO Buyers (Id, ShipTo) VALUES (@@IDENTITY, 'Somewhere');
c# inheritance entity-framework-6
add a comment |
I'm stuck trying to get EF to work with foreign keys in a TPT scenario. I think it is complicated in that one table has a one to many relationship, and the other has a one to one relationship.
This code is boiled down to illustrate the problem (GitHub: https://github.com/Dash/EFTest for VS project).
When I create a foreign key in the base Persons table I get an error about the type not being matched:
Product: FromRole: NavigationProperty 'Product' is not valid. Type
'Buyer' of FromRole 'Product_Buyers_Target' in AssociationType
'Product_Buyers' must exactly match with the type 'Person' on which
this NavigationProperty is declared on.
To try and tackle this, I move the Product navigation property up to the children, but then I get an error due to the ProductId column not existing in the database - it is trying to look in the derived tables and not in the base table.
I'm not entirely clear how to resolve this problem and have been going around in circles and googling until my eyes bleed. Can anybody help?
Model
public abstract class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Product Product { get; set; }
}
public class Buyer : Person
{
public string ShipTo { get; set; }
}
public class Seller : Person
{
public int Rating { get; set; } = 0;
}
public class Product
{
public int Id { get; set; }
public string Description { get; set; }
public virtual Seller Seller { get; set; }
public virtual IList<Buyer> Buyers { get; set; }
}
Schema
public class ProductSchema : EntityTypeConfiguration<Product>
{
public ProductSchema()
{
HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Description)
.HasMaxLength(256);
HasOptional(p => p.Seller)
.WithRequired(i => i.Product)
.Map(m => m.MapKey("ProductId"));
HasMany(p => p.Buyers)
.WithRequired(i => i.Product)
.Map(m => m.MapKey("ProductId"));
}
}
public class PersonSchema : EntityTypeConfiguration<Person>
{
public PersonSchema()
{
ToTable("Persons");
HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Name)
.HasMaxLength(128);
}
}
public class SellerSchema : EntityTypeConfiguration<Seller>
{
public SellerSchema()
{
ToTable("Sellers");
HasKey(s => s.Id)
.Property(s => s.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(s => s.Rating);
}
}
public class BuyerSchema : EntityTypeConfiguration<Buyer>
{
public BuyerSchema()
{
ToTable("Buyers");
HasKey(b => b.Id)
.Property(b => b.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(b => b.ShipTo)
.HasMaxLength(256);
}
}
SQL
CREATE TABLE Products (
Id INT IDENTITY PRIMARY KEY,
[Description] nvarchar(256),
)
create table Persons (
Id int IDENTITY PRIMARY KEY,
[Name] nvarchar(128),
ProductId INT NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products(Id)
)
CREATE TABLE Buyers (
Id INT PRIMARY KEY,
ShipTo nvarchar(256)
)
CREATE TABLE Sellers (
Id INT PRIMARY KEY,
Rating INT NOT NULL DEFAULT 0
)
DECLARE @ProductId int;
INSERT INTO Products ([Description]) VALUES ('Widget');
SET @ProductId = @@IDENTITY;
INSERT INTO Persons ([Name], ProductId) VALUES ('Bob the seller', @ProductId);
INSERT INTO Sellers (Id, Rating) VALUES (@@IDENTITY, 0);
INSERT INTO Persons ([Name], ProductId) VALUES ('Bert the buyer', @ProductId);
INSERT INTO Buyers (Id, ShipTo) VALUES (@@IDENTITY, 'Somewhere');
c# inheritance entity-framework-6
add following property toPerson
class ->public int ProductId { get; set; }
– Rudresha Parameshappa
Nov 13 '18 at 16:04
This doesn't work. In order to use a named property as a foreign key, you need to use .WithMany().HasForeignKey(), which doesn't work with a one-to-one relationship (Seller). And functionally, is no different from using a hidden foreign key that I'm using at the moment with MapKey().
– SirKumbskull
Nov 15 '18 at 10:49
add a comment |
I'm stuck trying to get EF to work with foreign keys in a TPT scenario. I think it is complicated in that one table has a one to many relationship, and the other has a one to one relationship.
This code is boiled down to illustrate the problem (GitHub: https://github.com/Dash/EFTest for VS project).
When I create a foreign key in the base Persons table I get an error about the type not being matched:
Product: FromRole: NavigationProperty 'Product' is not valid. Type
'Buyer' of FromRole 'Product_Buyers_Target' in AssociationType
'Product_Buyers' must exactly match with the type 'Person' on which
this NavigationProperty is declared on.
To try and tackle this, I move the Product navigation property up to the children, but then I get an error due to the ProductId column not existing in the database - it is trying to look in the derived tables and not in the base table.
I'm not entirely clear how to resolve this problem and have been going around in circles and googling until my eyes bleed. Can anybody help?
Model
public abstract class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Product Product { get; set; }
}
public class Buyer : Person
{
public string ShipTo { get; set; }
}
public class Seller : Person
{
public int Rating { get; set; } = 0;
}
public class Product
{
public int Id { get; set; }
public string Description { get; set; }
public virtual Seller Seller { get; set; }
public virtual IList<Buyer> Buyers { get; set; }
}
Schema
public class ProductSchema : EntityTypeConfiguration<Product>
{
public ProductSchema()
{
HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Description)
.HasMaxLength(256);
HasOptional(p => p.Seller)
.WithRequired(i => i.Product)
.Map(m => m.MapKey("ProductId"));
HasMany(p => p.Buyers)
.WithRequired(i => i.Product)
.Map(m => m.MapKey("ProductId"));
}
}
public class PersonSchema : EntityTypeConfiguration<Person>
{
public PersonSchema()
{
ToTable("Persons");
HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Name)
.HasMaxLength(128);
}
}
public class SellerSchema : EntityTypeConfiguration<Seller>
{
public SellerSchema()
{
ToTable("Sellers");
HasKey(s => s.Id)
.Property(s => s.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(s => s.Rating);
}
}
public class BuyerSchema : EntityTypeConfiguration<Buyer>
{
public BuyerSchema()
{
ToTable("Buyers");
HasKey(b => b.Id)
.Property(b => b.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(b => b.ShipTo)
.HasMaxLength(256);
}
}
SQL
CREATE TABLE Products (
Id INT IDENTITY PRIMARY KEY,
[Description] nvarchar(256),
)
create table Persons (
Id int IDENTITY PRIMARY KEY,
[Name] nvarchar(128),
ProductId INT NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products(Id)
)
CREATE TABLE Buyers (
Id INT PRIMARY KEY,
ShipTo nvarchar(256)
)
CREATE TABLE Sellers (
Id INT PRIMARY KEY,
Rating INT NOT NULL DEFAULT 0
)
DECLARE @ProductId int;
INSERT INTO Products ([Description]) VALUES ('Widget');
SET @ProductId = @@IDENTITY;
INSERT INTO Persons ([Name], ProductId) VALUES ('Bob the seller', @ProductId);
INSERT INTO Sellers (Id, Rating) VALUES (@@IDENTITY, 0);
INSERT INTO Persons ([Name], ProductId) VALUES ('Bert the buyer', @ProductId);
INSERT INTO Buyers (Id, ShipTo) VALUES (@@IDENTITY, 'Somewhere');
c# inheritance entity-framework-6
I'm stuck trying to get EF to work with foreign keys in a TPT scenario. I think it is complicated in that one table has a one to many relationship, and the other has a one to one relationship.
This code is boiled down to illustrate the problem (GitHub: https://github.com/Dash/EFTest for VS project).
When I create a foreign key in the base Persons table I get an error about the type not being matched:
Product: FromRole: NavigationProperty 'Product' is not valid. Type
'Buyer' of FromRole 'Product_Buyers_Target' in AssociationType
'Product_Buyers' must exactly match with the type 'Person' on which
this NavigationProperty is declared on.
To try and tackle this, I move the Product navigation property up to the children, but then I get an error due to the ProductId column not existing in the database - it is trying to look in the derived tables and not in the base table.
I'm not entirely clear how to resolve this problem and have been going around in circles and googling until my eyes bleed. Can anybody help?
Model
public abstract class Person
{
public int Id { get; set; }
public string Name { get; set; }
public virtual Product Product { get; set; }
}
public class Buyer : Person
{
public string ShipTo { get; set; }
}
public class Seller : Person
{
public int Rating { get; set; } = 0;
}
public class Product
{
public int Id { get; set; }
public string Description { get; set; }
public virtual Seller Seller { get; set; }
public virtual IList<Buyer> Buyers { get; set; }
}
Schema
public class ProductSchema : EntityTypeConfiguration<Product>
{
public ProductSchema()
{
HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Description)
.HasMaxLength(256);
HasOptional(p => p.Seller)
.WithRequired(i => i.Product)
.Map(m => m.MapKey("ProductId"));
HasMany(p => p.Buyers)
.WithRequired(i => i.Product)
.Map(m => m.MapKey("ProductId"));
}
}
public class PersonSchema : EntityTypeConfiguration<Person>
{
public PersonSchema()
{
ToTable("Persons");
HasKey(p => p.Id)
.Property(p => p.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(p => p.Name)
.HasMaxLength(128);
}
}
public class SellerSchema : EntityTypeConfiguration<Seller>
{
public SellerSchema()
{
ToTable("Sellers");
HasKey(s => s.Id)
.Property(s => s.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(s => s.Rating);
}
}
public class BuyerSchema : EntityTypeConfiguration<Buyer>
{
public BuyerSchema()
{
ToTable("Buyers");
HasKey(b => b.Id)
.Property(b => b.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(b => b.ShipTo)
.HasMaxLength(256);
}
}
SQL
CREATE TABLE Products (
Id INT IDENTITY PRIMARY KEY,
[Description] nvarchar(256),
)
create table Persons (
Id int IDENTITY PRIMARY KEY,
[Name] nvarchar(128),
ProductId INT NOT NULL,
FOREIGN KEY (ProductId) REFERENCES Products(Id)
)
CREATE TABLE Buyers (
Id INT PRIMARY KEY,
ShipTo nvarchar(256)
)
CREATE TABLE Sellers (
Id INT PRIMARY KEY,
Rating INT NOT NULL DEFAULT 0
)
DECLARE @ProductId int;
INSERT INTO Products ([Description]) VALUES ('Widget');
SET @ProductId = @@IDENTITY;
INSERT INTO Persons ([Name], ProductId) VALUES ('Bob the seller', @ProductId);
INSERT INTO Sellers (Id, Rating) VALUES (@@IDENTITY, 0);
INSERT INTO Persons ([Name], ProductId) VALUES ('Bert the buyer', @ProductId);
INSERT INTO Buyers (Id, ShipTo) VALUES (@@IDENTITY, 'Somewhere');
c# inheritance entity-framework-6
c# inheritance entity-framework-6
asked Nov 13 '18 at 16:00
SirKumbskullSirKumbskull
1
1
add following property toPerson
class ->public int ProductId { get; set; }
– Rudresha Parameshappa
Nov 13 '18 at 16:04
This doesn't work. In order to use a named property as a foreign key, you need to use .WithMany().HasForeignKey(), which doesn't work with a one-to-one relationship (Seller). And functionally, is no different from using a hidden foreign key that I'm using at the moment with MapKey().
– SirKumbskull
Nov 15 '18 at 10:49
add a comment |
add following property toPerson
class ->public int ProductId { get; set; }
– Rudresha Parameshappa
Nov 13 '18 at 16:04
This doesn't work. In order to use a named property as a foreign key, you need to use .WithMany().HasForeignKey(), which doesn't work with a one-to-one relationship (Seller). And functionally, is no different from using a hidden foreign key that I'm using at the moment with MapKey().
– SirKumbskull
Nov 15 '18 at 10:49
add following property to
Person
class -> public int ProductId { get; set; }
– Rudresha Parameshappa
Nov 13 '18 at 16:04
add following property to
Person
class -> public int ProductId { get; set; }
– Rudresha Parameshappa
Nov 13 '18 at 16:04
This doesn't work. In order to use a named property as a foreign key, you need to use .WithMany().HasForeignKey(), which doesn't work with a one-to-one relationship (Seller). And functionally, is no different from using a hidden foreign key that I'm using at the moment with MapKey().
– SirKumbskull
Nov 15 '18 at 10:49
This doesn't work. In order to use a named property as a foreign key, you need to use .WithMany().HasForeignKey(), which doesn't work with a one-to-one relationship (Seller). And functionally, is no different from using a hidden foreign key that I'm using at the moment with MapKey().
– SirKumbskull
Nov 15 '18 at 10:49
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53284894%2fentity-framework-6-tpt-and-foreign-keys%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53284894%2fentity-framework-6-tpt-and-foreign-keys%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
add following property to
Person
class ->public int ProductId { get; set; }
– Rudresha Parameshappa
Nov 13 '18 at 16:04
This doesn't work. In order to use a named property as a foreign key, you need to use .WithMany().HasForeignKey(), which doesn't work with a one-to-one relationship (Seller). And functionally, is no different from using a hidden foreign key that I'm using at the moment with MapKey().
– SirKumbskull
Nov 15 '18 at 10:49