C# 代码优先复杂类型还是外键关系?
我正在用EF6编写一个MVC5应用程序,它允许用户输入工作时间表、工作笔记并通过电子邮件向客户发送更新 我希望我的数据库结构由3个表组成(计时器、工作通知和电子邮件)。我可以有3个这样的模型C# 代码优先复杂类型还是外键关系?,c#,entity-framework,C#,Entity Framework,我正在用EF6编写一个MVC5应用程序,它允许用户输入工作时间表、工作笔记并通过电子邮件向客户发送更新 我希望我的数据库结构由3个表组成(计时器、工作通知和电子邮件)。我可以有3个这样的模型 [Table("Timers")] public partial class TimerModel { public int ID { get; set; } public string User { get; set; } ...etc public virtual Cu
[Table("Timers")]
public partial class TimerModel
{
public int ID { get; set; }
public string User { get; set; }
...etc
public virtual CustomerEmailModel CustomerEmail { get; set; }
}
[Table("JobNotes")]
public partial class JobNoteModel
{
public int ID { get; set; }
[Column("Username")]
public string User { get; set; }
...etc
public virtual CustomerEmailModel CustomerEmail { get; set; }
}
[ComplexType]
public partial class CustomerEmailModel
{
[Display(Name = "Email Customer?")]
public bool SendEmail { get; set; }
[DataType(DataType.EmailAddress)]
public string To { get; set; }
public string Subject { get; set; }
[DataType(DataType.MultilineText)]
public string Body { get; set; }
}
但这显然不会创建电子邮件表,而是将属性添加到计时器和JobNotes表中(例如Email\u sendmail、Email\u to等)
如果我删除[ComplexType]注释,并将我的其他模型更改为具有
public int? EmailID { get; set; }
[ForeignKey("EmailID")]
public virtual CustomerEmailModel CustomerEmail { get; set; }
然后它确实创建了表,但我不确定如何添加新条目(即,电子邮件是动态添加的,具有0..1关系。这意味着我需要显式地添加到电子邮件中,获取添加的条目ID,然后将其分配给另一个模型(计时器或jobnote模型)EmailID
有更好的方法吗
谢谢你的帮助。如果你需要进一步的信息,请告诉我
编辑:
看来,我确实需要提供更多的信息,从我得到的答案到目前为止。
我有两个数据库。一个供应商提供的数据库,用于记录工作、时间表、员工、客户等信息的应用程序。我们称之为DB01。
还有一个数据库(称为DB02)用于我的应用程序(它是一个移动应用程序,用户可以记录时间表或工作通知信息,并将其提交给DB01)
移动应用程序具有具有以下按键输入的用户界面;
开始时间、停止时间、休息时间、作业选择器(下拉列表)、时间表标题、时间表注释、向客户发送电子邮件(复选框)、地址、主题、正文
因此,复杂类型确实可以正常工作(这也是我在interm中使用的)。但是,因为我有另一个页面,也可以向客户发送电子邮件,所以我需要一个单独的电子邮件表(但是,我不希望必须单独保存电子邮件,然后将其分配到时间表或工作通知单)
还有-我需要的唯一表(对于DB02),是存储时间表、作业备忘和电子邮件数据的表。一旦提交了时间表或作业备忘,就可以将其删除或存档。我只需要这些表,因为所有其他相关信息都包含在DB01中。我可以从DB02的视图中检索此数据,并且可以使用存储过程fr将信息从DB02提交到DB01om DB02。(DB02将DB01作为链接服务器)这是一个将外键与EF6一起使用的简单示例
public class A
{
public int Id { get; set; }
public virtual B Bobject { get; set; }
public int BId;
public virtual ICollection<C> Cs { get; set; }
}
public class B
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<A> As { get; set; }
}
}
public class C
{
public int Id { get; set; }
public string TransactionId { get; set; }
public virtual A Aobj { get; set; }
public int AId { get; set; }
}
公共A类
{
公共int Id{get;set;}
公共虚拟B对象{get;set;}
公开招标;
公共虚拟ICollection Cs{get;set;}
}
公共B级
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection为{get;set;}
}
}
公共C类
{
公共int Id{get;set;}
公共字符串TransactionId{get;set;}
公共虚拟A Aobj{get;set;}
公共int-AId{get;set;}
}
首先,您的数据库有相当大的问题,而且您没有清楚地定义不同的数据集
我已经重新开发了您试图使用Fluent API实现的功能
public class TimeSheet
{
public TimeSheet()
{
this.TimeSheetId = Guid.NewGuid()
.ToString();
}
public virtual Employee Employee { get; set; }
public string EmployeeId { get; set; }
public virtual Job Job { get; set; }
public string JobId { get; set; }
public string TimeSheetId { get; set; }
}
public class Employee
{
public Employee()
{
this.EmployeeId = Guid.NewGuid()
.ToString();
}
public string EmployeeId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public virtual ICollection<TimeSheet> TimeSheets { get; set; }
public virtual ICollection<Mail> MailsSent { get; set; }
}
public class Job
{
public Job()
{
this.JobId = Guid.NewGuid()
.ToString();
}
// One job will have one client
public virtual Client Client { get; set; }
public string ClientId { get; set; }
public string JobId { get; set; }
public string Name { get; set; }
public string Notes { get; set; }
// A Job may have many time sheets
public virtual ICollection<TimeSheet> TimeSheets { get; set; }
}
public class Client
{
public Client()
{
this.ClientId = Guid.NewGuid()
.ToString();
}
public string ClientId { get; set; }
public string EmailAddress { get; set; }
// A client can have many work packages / jobs.
public virtual ICollection<Job> WorkPackages { get; set; }
public virtual ICollection<Mail> Mails { get; set; }
}
public class Mail
{
public Mail()
{
this.MailId = Guid.NewGuid()
.ToString();
}
// A mail item will reference one client.
public virtual Client Client { get; set; }
public string ClientId { get; set; }
public string MailId { get; set; }
public string Subject { get; set; }
public string Body { get; set; }
public string EmployeeId { get; set; }
// A mail item will also originate from an employee
public virtual Employee Employee { get; set; }
// This doesn't belong here... as if it isn't
// being sent, then it wouldn't make sense to create
// create the email in the first place...
// If you want to queue emails, rename the field to `IsSent`
//
// public bool SendEmail { get; set; }
}
public class TimeSheetConfiguration : EntityTypeConfiguration<TimeSheet>
{
public TimeSheetConfiguration()
{
this.ToTable("TimeSheets");
this.HasKey(timeSheet => timeSheet.TimeSheetId);
this.Property(property => property.TimeSheetId).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(property => property.JobId) .IsRequired();
this.Property(property => property.EmployeeId) .IsRequired();
this.HasRequired(timeSheet => timeSheet.Job) .WithMany(job => job.TimeSheets).HasForeignKey(timeSheet => timeSheet.JobId);
this.HasRequired(timeSheet => timeSheet.Employee).WithMany(emp => emp.TimeSheets).HasForeignKey(timeSheet => timeSheet.EmployeeId);
}
}
public class EmployeeConfiguration : EntityTypeConfiguration<Employee>
{
public EmployeeConfiguration()
{
this.ToTable("Employees");
this.HasKey(emp => emp.EmployeeId);
this.Property(property => property.EmployeeId) .IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(property => property.FirstName) .IsRequired();
this.Property(property => property.LastName) .IsOptional();
this.Property(property => property.EmailAddress).IsRequired();
this.HasMany(employee => employee.TimeSheets).WithRequired(time => time.Employee).HasForeignKey(time => time.EmployeeId);
this.HasMany(employee => employee.MailsSent) .WithRequired(mail => mail.Employee).HasForeignKey(mail => mail.EmployeeId);
}
}
public class ClientConfiguration : EntityTypeConfiguration<Client>
{
public ClientConfiguration()
{
this.ToTable("Clients");
this.HasKey(client => client.ClientId);
this.Property(property => property.ClientId) .IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(property => property.EmailAddress).IsRequired();
this.HasMany(property => property.WorkPackages).WithRequired(job => job.Client) .HasForeignKey(job => job.ClientId);
this.HasMany(property => property.Mails) .WithRequired(mail => mail.Client).HasForeignKey(mail => mail.ClientId);
}
}
public class JobConfiguration : EntityTypeConfiguration<Job>
{
public JobConfiguration()
{
this.ToTable("Jobs");
this.HasKey(job => job.JobId);
this.Property(property => property.JobId) .IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(property => property.Name) .IsRequired();
this.Property(property => property.ClientId).IsRequired();
this.Property(property => property.Notes) .IsRequired();
this.HasMany(job => job.TimeSheets).WithRequired(time => time.Job) .HasForeignKey(time => time.JobId);
this.HasRequired(job => job.Client).WithMany (client => client.WorkPackages).HasForeignKey(job => job.ClientId);
}
}
public class MailConfiguration : EntityTypeConfiguration<Mail>
{
public MailConfiguration()
{
this.ToTable("Mails");
this.HasKey(mail => mail.MailId);
this.Property(property => property.MailId) .IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(property => property.ClientId) .IsRequired();
this.Property(property => property.EmployeeId).IsRequired();
this.Property(property => property.Subject) .IsRequired();
this.Property(property => property.Body) .IsRequired();
this.HasRequired(mail => mail.Client) .WithMany(client => client.Mails) .HasForeignKey(mail => mail.ClientId);
this.HasRequired(mail => mail.Employee).WithMany(employee => employee.MailsSent).HasForeignKey(mail => mail.EmployeeId);
}
}
public class ExampleContext : DbContext
{
public DbSet<Mail> Mails { get; set; }
public DbSet<Job> Jobs { get; set; }
public DbSet<Client> Clients { get; set; }
public DbSet<Employee> Employees { get; set; }
public DbSet<TimeSheet> TimeSheets { get; set; }
/// <summary>
/// This method is called when the model for a derived context has been initialized, but
/// before the model has been locked down and used to initialize the context. The default
/// implementation of this method does nothing, but it can be overridden in a derived class
/// such that the model can be further configured before it is locked down.
/// </summary>
/// <remarks>
/// Typically, this method is called only once when the first instance of a derived context
/// is created. The model for that context is then cached and is for all further instances of
/// the context in the app domain. This caching can be disabled by setting the ModelCaching
/// property on the given ModelBuidler, but note that this can seriously degrade performance.
/// More control over caching is provided through use of the DbModelBuilder and DbContextFactory
/// classes directly.
/// </remarks>
/// <param name="modelBuilder">The builder that defines the model for the context being created. </param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new MailConfiguration());
modelBuilder.Configurations.Add(new ClientConfiguration());
modelBuilder.Configurations.Add(new EmployeeConfiguration());
modelBuilder.Configurations.Add(new TimeSheetConfiguration());
modelBuilder.Configurations.Add(new JobConfiguration());
base.OnModelCreating(modelBuilder);
}
}
公共类时间表
{
公共时间表()
{
this.TimeSheetId=Guid.NewGuid()
.ToString();
}
公共虚拟员工{get;set;}
公共字符串EmployeeId{get;set;}
公共虚拟作业作业{get;set;}
公共字符串JobId{get;set;}
公共字符串时间表{get;set;}
}
公营雇员
{
公职人员()
{
this.EmployeeId=Guid.NewGuid()
.ToString();
}
公共字符串EmployeeId{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串电子邮件地址{get;set;}
公共虚拟ICollection时间表{get;set;}
公共虚拟ICollection MailsSent{get;set;}
}
公开课工作
{
公职()
{
this.JobId=Guid.NewGuid()
.ToString();
}
//一个作业将有一个客户机
公共虚拟客户端{get;set;}
公共字符串ClientId{get;set;}
公共字符串JobId{get;set;}
公共字符串名称{get;set;}
公共字符串注释{get;set;}
//一份工作可能有很多时间表
公共虚拟ICollection时间表{get;set;}
}
公共类客户端
{
公共客户机()
{
this.ClientId=Guid.NewGuid()
.ToString();
}
公共字符串ClientId{get;set;}
公共字符串电子邮件地址{get;set;}
//客户机可以有许多工作包/作业。
公共虚拟ICollection工作包{get;set;}
公共虚拟ICollection邮件{get;set;}
}
公营邮件
{
公共邮件()
{
this.MailId=Guid.NewGuid()
.ToString();
}
//邮件项目将引用一个客户端。
公共虚拟客户端{get;set;}
公共字符串ClientId{get;set;}
公共字符串MailId{get;set;}
公共字符串主题{get;set;}
公共字符串体{get;set;}
公共字符串EmployeeId{get;set;}
//邮件项目也将来自员工
公共虚拟员工{get;set;}
//这不属于这里……好像不是
//如果被发送出去,那么创造就没有意义了
//首先创建电子邮件。。。
//如果要对电子邮件进行排队,请将该字段重命名为“IsSent”`
//
//公共bool sendmail{get;set;}
}
公共类时间表配置:EntityTypeConfiguration
{
公共时间表配置()
{
本表为可折叠表(“时间表”);
this.HasKey(timeSheet=>timeSheet.TimeSheetId);
this.Property(Property=>Property.TimeSheetId).IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
这是我的财产