I have "info" table with some fields that point to "id" column of "file_uploads" table. Also I third table with fk to "file_uploads", lets call it "another_table". How can I describe relationships in EF fluent api to use Linq Join or Include Queries?
InfoRecord {
public long Id {get; set;}
public long File1Id {get; set;}
public long File2Id {get; set;}
public long File3Id {get; set;}
public List<FileUploadRecord> Files {get; set;}
}
FileUploadRecord {
public long Id {get; set;}
public long Url {get; set;}
public InfoRecord Info {get; set;}
}
AnotherTableRecord {
public long Id {get; set;}
public long ImageId {get; set;}
public long FileUploadRecord Image { get; set; }
}
I know that I can create simple raw sql query with join and it will work, but It doesn't work with Linq .Include or .Join. I've tried to solve it by different ways, bu EF throw errors about bad FK relations.
I think you need to tweak your models a little bit. Right now, the InfoRecord
table has three columns pointing to the files table. The problem with that is: What if tomorrow you need to support more files? Adding more columns is not optimal. The process of fixing this is what's called Database Normalization .
If InfoRecord
needs "several columns to point to an id" on FileUpload
, you have a one-to-many
relationship - One InfoRecord
can have one or more files. We can achieve normalization using 3 tables:
1 - FileUpload
(the actual files, most basic entity. No relationships here.)
public class FileUpload
{
public long Id { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
}
2 - InfoRecord
- As your question, a InfoRecord can have many files:
public class InfoRecord
{
public long Id { get; set; }
public string Title { get; set; }
public ICollection<FileUploadRecord> Files { get; set; }
}
And lastly, the entity that "glues" them together:
3 - FileUploadRecord
- It has an FK
to FileUpload
and to InfoRecord
public class FileUploadRecord
{
public long Id { get; set; }
// FK to InfoRecord. Usefull for update scenarious
// without having to load the whole entity.
public long InfoRecordId { get; set; }
public InfoRecord InfoRecord { get; set; }
// FK To the actual file upload
public long FileId { get; set; }
public FileUpload FileUpload { get; set; }
}
Then you can configure it using the FluentAPI
like this:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Configure the Entity that "glues" InfoRecord and FileUploads.
// One InfoRecord can have many files, so we need a table to store that relationship.
modelBuilder.Entity<FileUploadRecord>()
.HasOne(s => s.InfoRecord)
.WithMany(g => g.Files)
.HasForeignKey(s => s.InfoRecordId);
modelBuilder.Entity<FileUploadRecord>()
.HasOne(p => p.FileUpload)
.WithMany()
.HasForeignKey(p => p.FileId);
}
And to query using .Include
like you wanted is easy now. The query below loads all InfoRecords
with each respective files.
var recordsWithFiles = context.InfoRecords
.Include(p => p.Files)
.ThenInclude(p => p.FileUpload);
This is how the DB schema will look like:
As per the "another_table", looks like it's a simple one-to-one
relationship so, you can just use plain EF Core Conventions for it. Of course .Include
also works here.
public class AnotherTableRecord
{
public long Id { get; set; }
// FK To the actual file upload
public long ImageId { get; set; }
public FileUpload Image { get; set; }
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.