Вопрос

I want to implement several extensions for Entity framework. Let met take this one as an example.

void InsertOrUpdate<T, TUpdateFields, TInsertFields, TKey>(
    this DbContext context,
    IEnumerable<T> data,
    Expression<Func<T, TUpdateFields>> updateFields,
    Expression<Func<T, TInsertFields>> insertFields,
    Expression<Func<T, TKey>> key)

And it is supposed to be used like this.

var dc = new SomeContext();
var user = new User() { /* initialize */ };
var array = new[] { user };
dc.InsertOrUpdate(
    array, 
    x => new {
        x.UserName,
        x.Password,
        x.LastLoggedIn
    },
    x => new {
        x.UserName,
        x.Password,
        x.Email,
        x.DateAdded,
        x.LastLoggedIn
    },
    x => x.UserName);

The method will generate an sql string and pass it into the DbContext.Database.ExecuteSqlCommand method. But in order to generate the sql I need to extract the table and field names from the model information, in case they are different from class and property names.

(For example UserName property corresponds to user_name field in DB)

I know that they can be set in the entity itself as data annotations, defined in the modelbuilder directly in OnModelCreating(DbModelBuilder) method of DbContext or defined in form of EntityTypeConfiguration<T> implementation and passed into the model builder configuration in the same method.

How can I retrieve tables' and fields' names from the DbContext instance? Is it possible at all?

Это было полезно?

Решение

I appears to be really easy. If the following is the class definition

[Table("User")]
public class User {
     [Column("user_id")]
     public Int32 UserId {get;set;}
     [Column("user_name")]
     public String UserName {get;set;}
     [Column("email")]
     public String Email {get;set;}
     [Column("join_date")]
     public DateTime DateAdded {get;set;}
     [Column("password")]
     public String Password {get;set;}
     [Column("last_logged_in")]
     public DateTime LastLoggedIn {get;set;}
}

I could just use the following technique

void InsertOrUpdate<T, TUpdateFields, TInsertFields, TKey>(
    this DbContext context,
    IEnumerable<T> data,
    Expression<Func<T, TUpdateFields>> updateFields,
    Expression<Func<T, TInsertFields>> insertFields,
    Expression<Func<T, TKey>> key){

    var sql = context.Set<T>().Select(updateFields).ToString();
    // Do stuff
}

eventually the sql variable will contain something like this

SELECT
1 AS [C1],
[Extent1].[user_name] AS [user_name],
[Extent1].[password] AS [password],
[Extent1].[last_logged_in] AS [last_logged_in]
FROM [dbo].[tbUser] AS [Extent1]

This statement can be parsed to find out the table and column names. The columns in the produced sql appears in the same order as they are indicated in the anonymous type

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top