3

enter image description here

We have a requirement that several tables need to be referred in a one table as shown in the diagram.

Please note that the diagram is NOT the correct DB model but just represent what our requirement. Can you suggest a proper way to implement above in SQL Server DB and Entity Framework 6?

Example: A sales order (in SalesOrder table) can have multiple files and those uploaded file details will be stored in UploadedFile table. Likewise OrderTable and Invoice too.

So we need to have a proper DB model with FK relationships between FileUpload table with each other related table.

Note: All tables PKs are auto-increment int values and we may need add more entities (tables) in future

  • Do you intend to use Code First? – Renato Oct 23 '18 at 13:17
  • you can save the three id of the 3 tables in one table then make relation between the new table and the uploaded file – Safaa Abd El Hamid Oct 23 '18 at 13:24
  • Possible duplicate of [Foreign Key to multiple tables](https://stackoverflow.com/questions/7844460/foreign-key-to-multiple-tables). Think this mirrors your problem pretty well, so I'll delete my post as it's covered in more detail in the linked post. – Tanner Oct 23 '18 at 13:27
  • @Tishan, I have written a sample using EF Code First, if you are using C# and you would like to have an alternative, please add the C# tag and reply to me here, and I will add the sample as an answer. Thanks. – Renato Oct 23 '18 at 14:30
  • Thanks @Tanner for the link, I checked the answer in there and seems 4th option is better, but that solution make the entity tables have a column just for it's type and its always same for every record in that particular  table, for an example, my SalesOrder table should have a column like "UploadTypeId" which always value is same (ie. 1), So just asking is that OK when considering good DB design? – Tishan Madhawa Oct 23 '18 at 15:27
  • Thanks @Renato, yes please add your sample code, that could helps us. – Tishan Madhawa Oct 23 '18 at 15:36
  • I added it below, with the C# tag the proper formatting is applied. **However**, if you already have created a DB, you may consider using DB First or Code First from existing DB. – Renato Oct 23 '18 at 16:14

2 Answers2

2

In order to provide you an alternative, as you said you are using Entity Framework, here is a sample of Code First implementation done on C#. You can create and update the schema via Package Manager Console migrations, within Visual Studio. I have used the Fluent API in order to define the relationships, as this is recommended over the alternative.

public class SampleContext : DbContext
{
    public SampleContext()
        : base("name=YourConnection")
    {
    }

    public DbSet<SalesOrder> SalesOrders { get; set; }
    public DbSet<CreditOrder> CreditOrders { get; set; }
    public DbSet<Invoice> Invoices { get; set; }
    public DbSet<UploadedFile> UploadedFiles { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<SalesOrder>()
            .HasKey(so => so.Id);

        modelBuilder.Entity<CreditOrder>()
            .HasKey(co => co.Id);

        modelBuilder.Entity<Invoice>()
            .HasKey(i => i.Id);

        modelBuilder.Entity<UploadedFile>()
            .HasKey(u => u.Id);

        modelBuilder.Entity<UploadedFile>()
            .HasRequired(u => u.SalesOrder)
            .WithMany(s => s.UploadedFiles)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<UploadedFile>()
            .HasRequired(u => u.CreditOrder)
            .WithMany(c => c.UploadedFiles)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<UploadedFile>()
            .HasRequired(u => u.Invoice)
            .WithMany(c => c.UploadedFiles)
            .WillCascadeOnDelete(false);

        modelBuilder.Entity<UploadedFile>()
            .Property(uf => uf.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<SalesOrder>()
            .Property(so => so.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<CreditOrder>()
            .Property(co => co.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        modelBuilder.Entity<Invoice>()
            .Property(i => i.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        base.OnModelCreating(modelBuilder);
    }
}

// Collections of navigation properties should be included in classes for a one-to-many relationship

public class SalesOrder
{
    public int Id { get; set; }
    public string MyColumn { get; set; }
    public IList<UploadedFile> UploadedFiles { get; set; }
}

public class CreditOrder
{
    public int Id { get; set; }
    public string MyColumn { get; set; }
    public IList<UploadedFile> UploadedFiles { get; set; }
}

public class Invoice
{
    public int Id { get; set; }
    public string MyColumn { get; set; }
    public IList<UploadedFile> UploadedFiles { get; set; }
}

public class UploadedFile
{
    public int Id { get; set; }
    public SalesOrder SalesOrder { get; set; }
    public CreditOrder CreditOrder { get; set; }
    public Invoice Invoice { get; set; }
    public string FilePath { get; set; }
    public string FileType { get; set; }
}

public class SalesOrder
{
    public int Id { get; set; }
    public string MyColumn { get; set; }
    public IList<UploadedFile> UploadedFiles { get; set; }
}

public class CreditOrder
{
    public int Id { get; set; }
    public string MyColumn { get; set; }
    public IList<UploadedFile> UploadedFiles { get; set; }
}

public class Invoice
{
    public int Id { get; set; }
    public string MyColumn { get; set; }
    public IList<UploadedFile> UploadedFiles { get; set; }
}

public class UploadedFile
{
    public int Id { get; set; }
    public SalesOrder SalesOrder { get; set; }
    public CreditOrder CreditOrder { get; set; }
    public Invoice Invoice { get; set; }
    public string FilePath { get; set; }
    public string FileType { get; set; }
}
Renato
  • 556
  • 5
  • 18
1

Before Reading My Answer take notice in the below information:

A better answer can be found at this previous post at Foreign Key to multiple tables.


My Answer:

Refer here for more information from the Creating Tables documentation off of the MDSN page.

The design I went for gave each table there own id as the Primary Key. Then I used the UploadedFile table to add references to each of these tables in the shape of Foreign Keys.

I have created a few dummy scripts that might help you create these tables. Please let me know if this helps. Thank you!

SQL Scripts:

SalesOrder Table:

Create Table dbo.SalesOrder(
SalesOrderID int not null, identity primary key,
--enter whatever other columsn you have here
)

CreditOrder Table:

Create Table sbo.CreditOrder(
CreditOrderID int not null, identity primary key,
--enter whatever other columsn you have here
)

Invoice Table:

Create Table dbo.Invoice(
InvoiceID int not null, identity primary key,
--enter whatever other column you have here
)

UploadedFile Table:

Create table dbo.UploadedFile(
UploadFileID int not null identity primary key,
SalesOrderID int null Foreign Key References SalesOrder(SalesOrderID),
CreditOrderID int null Foreign Key References CreditOrder(CreditOrderID),
InvoiceID int null Foreign Key References CreditOrder(InvoiceID),
--enter whatever other columns you have here
)
B. Cratty
  • 1,725
  • 1
  • 17
  • 32
  • From a stack overflow user is it better that I delete it? Or does it really matter? @Tanner – B. Cratty Oct 23 '18 at 13:36
  • How bout the changes I just made? @Tanner – B. Cratty Oct 23 '18 at 13:47
  • Thank you for the reply, we considered this way but the problem is as noted in the question, there can be more tables add in future which also needed upload files. So in that case we need to modify the UploadedFile table for adding new reference columns. We are not sure whether that’s the proper way to achieve our goal. – Tishan Madhawa Oct 23 '18 at 15:45
  • They way I have it structured allows you to add more reference columns as you move on from these base tables, but okay thank you for considering this as a solution. @TishanMadhawa – B. Cratty Oct 23 '18 at 15:58