Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

EntityFramework (Data Annotations only) Relationship not resolving with ID

I have the relationship of two classes.

class ClassA {
   [Required]
   int Id { get; set; }

   [Required]
   public int OtherId { get; set; }

   [ForeignKey("OtherId")]
   public ClassB? Other{ get; set; }
}
class ClassB {
   [Required]
   int Id { get; set; }

   public IEnumerable<ClassA> Others { get; set; } = new List<ClassA>();
}

When I insert an object of ClassA I do it like this:

await this.Context.Set<ClassA>().AddAsync(new ClassA() { OtherId = 2 } );
await this.Context.SaveChangesAsync();

This works perfectly on the live database (Azure SQL DB). When I add the class like this and fetch it from the database later on (e.g. literally after the SaveChangesAsync), I get the object, INCLUDING the object ClassA.Other.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

When I run the code on an in-memory DB on the other hand, it does not work! The inserting step works, but does NOT validate if the ID (ClassA.OtherId) exists. This means, I can set the ClassA.OtherId to "12345" without any problems, even if I do not have a single entry of ClassB. If I insert a valid ClassA.OtherId it works as well, but when I fetch the object from the database, ClassA.Other is null.

Just to clarify, why I write ClassB? Other instead of ClassB Other. This is only a simplified version of the code, I tested quickly, but in our production environment, we include/exclude certain fields from certain queries for performance reasons. Therefore, it is possible that the property might be null at certain times.

>Solution :

Most In-memory Testdoubles have some flaws in that regard, instead try to use the SQlite Provider, for it behaves more like a real Database

Example for the Configuration:

public static class EfDbContextSqliteBuilderConfigurationFactory
{
    internal static Action<DbContextOptionsBuilder> GetSqliteDatabaseOption()
    {
        const string tempDataBaseFolder = "Database";
        EnsureSqliteTempDatabaseFolderExists(tempDataBaseFolder);

        return c => c.UseSqlite(new SqliteConnection($"DataSource={tempDataBaseFolder}\\{Guid.NewGuid()}.db"));
    }

    private static void EnsureSqliteTempDatabaseFolderExists(string tempDataBaseFolder)
    {
        if (!Directory.Exists(tempDataBaseFolder))
        {
            Directory.CreateDirectory(tempDataBaseFolder);
        }
    }
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading