我正在使用EF6编写MVC5应用程序,允许用户输入作业时间表,工作说明并通过电子邮件向客户发送更新。
我希望我的数据库结构由3个表组成(Timers,JobNotes和Emails)。我可以有3个这样的模型;
[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; }
}
但这显然不会创建Email表,而是将属性添加到Timer和JobNotes表(例如Email_SendEmail,Email_To等)。
如果我删除[ComplexType]注释,并将我的其他模型更改为;
public int? EmailID { get; set; }
[ForeignKey("EmailID")]
public virtual CustomerEmailModel CustomerEmail { get; set; }
然后它确实创建了表格,但后来我不确定如何添加新条目(即电子邮件是动态添加的,具有0..1关系。这意味着我需要添加到明确地发送电子邮件,获取添加的条目ID,然后将其分配给其他模型(计时器或作业模型)EmailID。
有更好的方法吗?
提前感谢您的帮助。如果您需要任何进一步的信息,请与我们联系。
编辑: 看来我确实需要从我到目前为止得到的答案中提供更多信息。 我有两个数据库在起作用。供应商提供的数据库,用于记录作业,时间表,员工,客户等信息的应用程序。让我们称之为DB01。 我的应用程序的数据库(称为DB02)(用户可以记录时间表或作业信息的移动应用程序,并将其提交给DB01)。
移动应用程序具有用户界面,其具有以下键输入; 开始时间,停止时间,休息时间,作业选择器(下拉列表),时间表标题,时间表备注,向客户发送电子邮件(复选框),收件人地址,主题,正文。
因此,复杂类型可以正常工作(并且是我在interm中使用的)。但是,因为我还有另一个页面可以通过电子邮件发送给客户,我想要一个单独的电子邮件表(但是,我不想单独保存电子邮件,然后将其分配给时间表或工作单)
此外 - 我需要的唯一表(对于DB02)是存储时间表,作业单和电子邮件数据的表。提交时间表或作业单后,可以将其删除或存档。我只需要这些表,因为所有其他相关信息都包含在DB01中。我可以从DB02上的视图中检索此数据,并且可以使用DB02中的存储过程将DB02中的信息提交到DB01。 (DB02将DB01作为链接服务器)
答案 0 :(得分:0)
This is a simple example of the use of foreign keys with 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; }
}
答案 1 :(得分:0)
您的数据库开头存在很大问题,而且您没有明确定义不同的数据集。
我已经重新开发了您尝试使用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);
}
}