多重继承(也许是抽象 class?)C# Entity Framework
Multiple Inheritance (maybe Abstract class?) C# Entity Framework
过去几周,我一直致力于使用 Visual Studio 2015 在 c# 上开发基于 Entity Framework 6(代码优先)的数据库。
我目前正在处理继承提供的所有选项。
在这一点上,按照数据库的标准,我应该用主键实现多重继承。
这是什么意思?
这意味着我应该实现一个从另一个 class 继承的 class 并拥有自己的 PK 以识别他与父 class 不同。此时我可以使用 TPC 实现它,使父 class 抽象并且不在父上定义任何 PK。这是此时的代码示例(这有效并且我已经测试过)
public abstract class Person
{
public string Name { get; set; }
public string LastName { get; set; }
}
[Table("Students")]
public class Student : Person
{
[Key]public int Id_student { get; set; }
public string code_s { get; set; }
public virtual ICollection<Course> courses { get; set; }
}
然后我应该遵循的标准来构建我的数据库要求我实现另一个继承,以 Student 作为 Parent 并创建另一个继承自 Student 的 class。
我的第一个也是愚蠢的想法是让它像写
一样简单
ChildOfChild : Student
但显然没有用。
然后我想到了使 Student class Abstract 成为可能,但是当我声明 Student class Abstract 时,它并没有让我实例化它并为 table.我不确定是否有任何其他方法可以使用 abstract class 或任何其他可用于开发此方法的方法来执行此操作。
如果您不理解我正在尝试解决的问题,这就是我想要的代码示例。
public abstract class Person
{
public string Name { get; set; }
public string LastName { get; set; }
}
[Table("Students")]
public class Student : Person
{
[Key]public int Id_student { get; set; }
public string code_s { get; set; }
public virtual ICollection<Course> courses { get; set; }
}
[Table("ExchangeStudent")]
public class ExchangeStudent : Student
{
[Key]public int Id_exchange { get; set; }
public string HomeUniversity {get; set;}
}
您不能有两个主键。 Student
将 Id_student
定义为主键,然后在 ExchangeStudent
中将 Id_exchange
定义为主键。我会在 Person
中实现 属性 'Id' 并删除 Id_student
和 Id_exchange
属性。
public abstract class Student : Person
{
[Key]public int Id_student { get; set; }
}
public class LocalStudent : Student{
}
public class ExchangeStudent : Student
{
public string HomeUniversity {get; set;}
}
但我会考虑
public class Student : Person
{
[Key]public int Id_student { get; set; }
public string code_s { get; set; }
public virtual ICollection<Course> courses { get; set; }
public ExchangeInfo ExchangeInfo{get;set;}
}
public class ExchangeInfo : Student
{
[Key]public int Id_exchange { get; set; }
public Student Student{get;set;}
public string HomeUniversity {get; set;}
}
HomeUniversity 听起来像学生的属性吗?
与单个 table 学生一起工作而不是从 2 table 中选择 2 个学生会更符合 table,以找出谁真正在听课
另外,您将如何为 table 开设 link 课程,例如面向两个 table 学生和 ExchangeStudent 的课程?
会有 Person
没有 Id
吗?如果没有,给一个Person
一个Id
属性。用你的流利语言定义 API 在你为 TPC 建模的地方,这个 Id 是你的学生和交换生的主键。
public class Person
{
public int Id {get; set;
public string Name { get; set; }
public string LastName { get; set; }
}
public class Student : Person
{
// the primary key is in the base class
public string code_s { get; set; }
public virtual ICollection<Course> courses { get; set; }
}
public class ExchangeStudent : Student
{
// the primary key is in one of the base classes
public string HomeUniversity {get; set;}
}
您的 DbContext 将 TPC 配置为 this link
class MyDbContext : DbContext
{
public DbSet<Student> Students {get; set;}
public DbSet<ExchangeStudent> ExchangeStudents {get; set;}
protected override OnModelCreating(...)
{ // configure Student and ExcahngeStudent as TPC,
// if needed define primary key
modelBuilder.Entity<Student>()
.HasKey(student => student.Id)
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Students");
});
modelBuilder.Entity<ExchangeStudent>()
.HasKey(student => student.Id)
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("ExchangeStudents");
});
}
我不确定是否需要 HasKey
。因为主键跟在naming conventions之后,所以可能不需要。
使用 fluent API 以上属性的优点在于,它使您可以自由地在不同的数据库模型中使用相同的 类 和查询,只需指定不同的 DbContext。
根据我的理解,您需要两个 table,它们都具有自己的主键和外键来定义一对一关系。在您的 C# 代码中,您希望这些 table 具有继承关系。
我看到您使用 Entity Framework 执行此操作的唯一方法是拆分您的要求。首先创建代表您想要的 table 结构的数据库模型。
namespace DAO
{
public abstract class Person
{
public string Name { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string Nickname { get; set; }
}
//Use navigation property rather than inheritance to define the relationship
public class ExchangeStudent
{
public int ExchangeStudentId { get; set; }
public string HomeUniversity { get; set; }
public virtual Student Student { get; set; }
}
}
这给了我以下代码:
public override void Up()
{
CreateTable(
"dbo.ExchangeStudent",
c => new
{
ExchangeStudentId = c.Int(nullable: false, identity: true),
HomeUniversity = c.String(),
Student_StudentId = c.Int(),
})
.PrimaryKey(t => t.ExchangeStudentId)
.ForeignKey("dbo.Student", t => t.Student_StudentId)
.Index(t => t.Student_StudentId);
CreateTable(
"dbo.Student",
c => new
{
StudentId = c.Int(nullable: false, identity: true),
Nickname = c.String(),
Name = c.String(),
})
.PrimaryKey(t => t.StudentId);
}
现在如果您需要在 Student 和 ExchangeStudent 之间建立继承关系,您可以创建新对象以在不同的命名空间中定义
namespace BusinessObject
{
public abstract class Person
{
public string Name { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string Nickname { get; set; }
}
//ExchangeStudent derives from Student
public class ExchangeStudent : Student
{
public int ExchangeStudentId { get; set; }
public string HomeUniversity { get; set; }
}
}
然后你只需要创建一个 class 来映射这两个对象。也有第 3 方库可以为您执行此操作。
过去几周,我一直致力于使用 Visual Studio 2015 在 c# 上开发基于 Entity Framework 6(代码优先)的数据库。
我目前正在处理继承提供的所有选项。 在这一点上,按照数据库的标准,我应该用主键实现多重继承。 这是什么意思? 这意味着我应该实现一个从另一个 class 继承的 class 并拥有自己的 PK 以识别他与父 class 不同。此时我可以使用 TPC 实现它,使父 class 抽象并且不在父上定义任何 PK。这是此时的代码示例(这有效并且我已经测试过)
public abstract class Person
{
public string Name { get; set; }
public string LastName { get; set; }
}
[Table("Students")]
public class Student : Person
{
[Key]public int Id_student { get; set; }
public string code_s { get; set; }
public virtual ICollection<Course> courses { get; set; }
}
然后我应该遵循的标准来构建我的数据库要求我实现另一个继承,以 Student 作为 Parent 并创建另一个继承自 Student 的 class。 我的第一个也是愚蠢的想法是让它像写
一样简单ChildOfChild : Student
但显然没有用。
然后我想到了使 Student class Abstract 成为可能,但是当我声明 Student class Abstract 时,它并没有让我实例化它并为 table.我不确定是否有任何其他方法可以使用 abstract class 或任何其他可用于开发此方法的方法来执行此操作。 如果您不理解我正在尝试解决的问题,这就是我想要的代码示例。
public abstract class Person
{
public string Name { get; set; }
public string LastName { get; set; }
}
[Table("Students")]
public class Student : Person
{
[Key]public int Id_student { get; set; }
public string code_s { get; set; }
public virtual ICollection<Course> courses { get; set; }
}
[Table("ExchangeStudent")]
public class ExchangeStudent : Student
{
[Key]public int Id_exchange { get; set; }
public string HomeUniversity {get; set;}
}
您不能有两个主键。 Student
将 Id_student
定义为主键,然后在 ExchangeStudent
中将 Id_exchange
定义为主键。我会在 Person
中实现 属性 'Id' 并删除 Id_student
和 Id_exchange
属性。
public abstract class Student : Person
{
[Key]public int Id_student { get; set; }
}
public class LocalStudent : Student{
}
public class ExchangeStudent : Student
{
public string HomeUniversity {get; set;}
}
但我会考虑
public class Student : Person
{
[Key]public int Id_student { get; set; }
public string code_s { get; set; }
public virtual ICollection<Course> courses { get; set; }
public ExchangeInfo ExchangeInfo{get;set;}
}
public class ExchangeInfo : Student
{
[Key]public int Id_exchange { get; set; }
public Student Student{get;set;}
public string HomeUniversity {get; set;}
}
HomeUniversity 听起来像学生的属性吗? 与单个 table 学生一起工作而不是从 2 table 中选择 2 个学生会更符合 table,以找出谁真正在听课 另外,您将如何为 table 开设 link 课程,例如面向两个 table 学生和 ExchangeStudent 的课程?
会有 Person
没有 Id
吗?如果没有,给一个Person
一个Id
属性。用你的流利语言定义 API 在你为 TPC 建模的地方,这个 Id 是你的学生和交换生的主键。
public class Person
{
public int Id {get; set;
public string Name { get; set; }
public string LastName { get; set; }
}
public class Student : Person
{
// the primary key is in the base class
public string code_s { get; set; }
public virtual ICollection<Course> courses { get; set; }
}
public class ExchangeStudent : Student
{
// the primary key is in one of the base classes
public string HomeUniversity {get; set;}
}
您的 DbContext 将 TPC 配置为 this link
class MyDbContext : DbContext
{
public DbSet<Student> Students {get; set;}
public DbSet<ExchangeStudent> ExchangeStudents {get; set;}
protected override OnModelCreating(...)
{ // configure Student and ExcahngeStudent as TPC,
// if needed define primary key
modelBuilder.Entity<Student>()
.HasKey(student => student.Id)
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("Students");
});
modelBuilder.Entity<ExchangeStudent>()
.HasKey(student => student.Id)
.Map(m =>
{
m.MapInheritedProperties();
m.ToTable("ExchangeStudents");
});
}
我不确定是否需要 HasKey
。因为主键跟在naming conventions之后,所以可能不需要。
使用 fluent API 以上属性的优点在于,它使您可以自由地在不同的数据库模型中使用相同的 类 和查询,只需指定不同的 DbContext。
根据我的理解,您需要两个 table,它们都具有自己的主键和外键来定义一对一关系。在您的 C# 代码中,您希望这些 table 具有继承关系。
我看到您使用 Entity Framework 执行此操作的唯一方法是拆分您的要求。首先创建代表您想要的 table 结构的数据库模型。
namespace DAO
{
public abstract class Person
{
public string Name { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string Nickname { get; set; }
}
//Use navigation property rather than inheritance to define the relationship
public class ExchangeStudent
{
public int ExchangeStudentId { get; set; }
public string HomeUniversity { get; set; }
public virtual Student Student { get; set; }
}
}
这给了我以下代码:
public override void Up()
{
CreateTable(
"dbo.ExchangeStudent",
c => new
{
ExchangeStudentId = c.Int(nullable: false, identity: true),
HomeUniversity = c.String(),
Student_StudentId = c.Int(),
})
.PrimaryKey(t => t.ExchangeStudentId)
.ForeignKey("dbo.Student", t => t.Student_StudentId)
.Index(t => t.Student_StudentId);
CreateTable(
"dbo.Student",
c => new
{
StudentId = c.Int(nullable: false, identity: true),
Nickname = c.String(),
Name = c.String(),
})
.PrimaryKey(t => t.StudentId);
}
现在如果您需要在 Student 和 ExchangeStudent 之间建立继承关系,您可以创建新对象以在不同的命名空间中定义
namespace BusinessObject
{
public abstract class Person
{
public string Name { get; set; }
}
public class Student
{
public int StudentId { get; set; }
public string Nickname { get; set; }
}
//ExchangeStudent derives from Student
public class ExchangeStudent : Student
{
public int ExchangeStudentId { get; set; }
public string HomeUniversity { get; set; }
}
}
然后你只需要创建一个 class 来映射这两个对象。也有第 3 方库可以为您执行此操作。