Entity Framework Core

repository·main·Indexed 12 days ago

https://github.com/dotnet/efcore

A modern object-database mapper for .NET. It supports LINQ queries, change tracking, and schema migrations via a DbContext. The ecosystem includes the dotnet-ef CLI tool, various database providers (SQL Server, SQLite, Azure Cosmos DB, In-Memory), and specialized packages for design-time tooling, abstractions, and proxies for lazy-loading and change-tracking.

Tokens
25.8K
Snippets
95
Records
133
Agent score
96%

What's inside EF Core

  1. What is Entity Framework Core

    main
    Entity Framework Core (EF Core) is a modern object-database mapper for .NET (C#). It allows you to build a portable, high-level data access layer that supports LINQ queries, change tracking, updates, and schema migrations. It works across various databases including SQL Server, SQLite, MySQL, PostgreSQL, Oracle, and Azure Cosmos DB.
  2. What is ApiChief and how does it filter APIs

    main

    ApiChief is a tool for EF Core used to manage public API baselines and review artifacts for compiled assemblies. It helps track breaking changes and generate API summaries.

    When analyzing an assembly, ApiChief applies the following filtering logic:

    • It only includes the public/protected API surface.
    • It filters out any types located in namespaces ending with .Internal.
    • It filters out any APIs decorated with the [EntityFrameworkInternal] attribute.
  3. Resolve connection strings via IConfiguration

    main
    If you provide a connection string in the format name=MyConnection, EF Core will use the IConfiguration service from the service provider to resolve the actual connection string. It looks for the key "MyConnection" or "ConnectionStrings:MyConnection" within your configuration.
  4. Security considerations for Migration APIs

    main

    Migration APIs are designed for trusted values that are compiled into your application. They are not intended to handle untrusted input from end users.

    Warning: Certain migration APIs are 'pass-thru' in nature and do not perform validation or escaping. This includes:

    • The Sql(string) method.
    • The defaultValueSql parameter.

    Guidance: If you must pass input from an untrusted source to migration APIs, you must perform explicit validation to protect against SQL injection.

  5. Understand Arcade template shims and logic structure

    main

    Arcade's template architecture is divided into three functional types to manage the difference between standard and 1ES pipelines:

    • shim: An intermediate YAML file (found in templates/ or templates-official/) that acts as an entry point. It defines the is1ESPipeline parameter (set to true for templates-official and false for templates) and redirects to the actual logic.
    • logic: The actual base template logic, located primarily in the core-templates/ folder.
    • redirect: A file in core-templates/ that redirects back to the specific logic file in either templates/ or templates-official when the logic is dependent on the shim entry point used.

    Key structural rule: Templates at the stages, jobs, and job levels are implemented as shims. Templates at the steps and variables levels typically contain direct logic because they are too granular to require shims.

  6. Mitigate Cartesian Explosion in queries

    main

    Relational database JOINs can cause a "cartesian explosion," where the number of rows returned is the product of the rows in the joined tables, potentially leading to Denial of Service (DoS) through massive result sets.

    To mitigate this, use the .AsSplitQuery() method to instruct EF Core to execute multiple queries instead of a single large join.

  7. Define a DbContext and Entities

    main

    To use EF Core, you must create a class that inherits from DbContext, which represents your database session. You also define classes (entities) that represent the data structures in your database. Use DbSet<TEntity> properties within your DbContext to expose these entities for querying and saving.

    using Microsoft.EntityFrameworkCore;
    
    public class MyDbContext : DbContext
    {
        public DbSet<Customer> Customers { get; set; }
    }
    
    public class Customer
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
  8. Security guarantees for LINQ queries and updates

    main

    EF Core relational providers provide built-in protection against SQL injection through automatic parameterization and escaping:

    1. LINQ Queries: Any values supplied within a LINQ query (e.g., in a .Where() clause) are automatically parameterized or escaped.
    2. Update Pipeline: Values stored in entity properties (instance data) are automatically parameterized or escaped when using methods like Add() and SaveChanges().

    This ensures that even if values originate from untrusted end-user input, they are handled safely by the underlying database provider.

    // LINQ query example: lastName is automatically parameterized
    public IEnumerable<Customer> FindCustomers(string lastName)
    {
        using (var context = new CustomerContext())
        {
            return context.Customers
                .Where(c => c.LastName == lastName)
                .ToList();
        }
    }
    
    // Update example: firstName and lastName are automatically parameterized
    public Customer CreateCustomer(string firstName, string lastName)
    {
        using (var context = new CustomerContext())
        {
            var customer = new Customer 
            {
                FirstName = firstName,
                LastName = lastName
            };
    
            context.Customers.Add(customer);
            context.SaveChanges();
    
            return customer;
        }
    }
  9. Understand EF Core security guarantees for logging and messages

    main

    By default, EF Core provides the following security guarantees to prevent data leakage:

    • No Credentials in Messages: Connection string credentials are never included in log messages (though database names may be).
    • No Application Data in Messages: Messages (including Exception.Message, Exception.ToString, and ILogger.Write strings) do not contain application data (e.g., query results, entity values) by default.
    • No Application Data in Logging State: The state passed to ILogger.Write does not contain references to application data or objects from which application data can be obtained.

    WARNING: These guarantees are void if the IncludeSensitiveDataInLog flag is enabled.

  10. Understand EF Core's security guarantees regarding untrusted databases

    main

    EF Core is designed to handle untrusted result sets from a database. It does not load, construct, or execute code dynamically based on the data received; all types must be specified in the EF model in advance.

    Key security behaviors include:

    • Scaffolding Safety: The scaffolding feature (generating code from an existing database) is safe and cannot be used as a vector for Remote Code Execution (RCE) via malicious table or column names.
    • Data Serialization: EF does not assume property order during deserialization. For JSON, the discriminator ($type) is serialized first, followed by keys, in a deterministic order.
    • Exception Censorship: By default, EF Core censors sensitive data in exception messages, though schema information (property/column names) is not considered sensitive.
    • Complexity: EF performs $O(n)$ work relative to the size of the database response ($n$).
  11. When to use Microsoft.EntityFrameworkCore.Sqlite vs Microsoft.EntityFrameworkCore.Sqlite.Core

    main

    Deciding between the two SQLite provider packages depends on your requirement for the native SQLite binary:

    • Microsoft.EntityFrameworkCore.Sqlite: Use this for most standard applications. It automatically includes the necessary SQLite native binaries.
    • Microsoft.EntityFrameworkCore.Sqlite.Core: Use this only if you need to swap out the default SQLite binary for a different one. This requires manual installation of a binary package and manual initialization via SQLitePCL.Batteries_V2.Init();.