代码优先复杂类型或外键关系?

时间:2015-04-23 01:21:54

标签: c# entity-framework

我正在使用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作为链接服务器)

2 个答案:

答案 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);
    }
}