Linq to SQL,在没有新动态类型创建的情况下连接字段

时间:2016-09-15 12:34:29

标签: c# linq lambda linq-to-sql

我想将字段连接成一个非字段,这是同一模型的属性。

我有Person的模型,其中包含一个名为FullName的非字段属性(NotMapped):

public class Person
{
   public int Id{get;set;}
   public string firstname{get;set;}
   public string lastname{get;set;}

   [NotMapped]
   public string FullName{get;set;}
}

现在我要选择所有人及其FullName

FullName = string.format("{0} {1}",firstname, lastname);

我不希望在列出表后为每个人分配全名,因为它没有良好的性能和速度(约10K记录)

我不想使用新的选择(动态类型),如下所示

var list = from pf in db.Persons 
           select new 
                  {
                     Person = pf,
                     FullName = string.format("{0} {1}", pf.firstname, pf.lastname)
                  }
List<Person> persons = new List<Person>();

// bad performance
foreach(var item in list)
{
    item.Person.FullName = item.FullName;
    persons.Add(item);
}

除非你为它提供一个动态lambda函数,它具有通用模型类型和连接字段公式的表达式。

例如:

public List<TModel> GetList<TModel>(Expression<Func<TModel, string>> cField = null,...)
{
//all should done in database side with one query
//select all records include FullName
}

我不想使用FullName.get

public string FullName
{
     get { return string.format("{0} {1}", pf.firstname, pf.lastname); }
} 

因为它与foreach方法相同,并且在datagridview中使用该类时性能较差。

换句话说,我需要的是一个选择所有人及其全名的linq查询。

请注意,数据库选择后的任何分配(特别是在使用界面时)都有不良的性能。

2 个答案:

答案 0 :(得分:1)

更改您的型号:

public class Person
{
 public int Id{get;set;}
 public string firstname{get;set;}
 public string lastname{get;set;}

 [NotMapped]
 public string FullName => firstname + " " + lastname;
}

答案 1 :(得分:0)

只需使用一些Dto

public class PersonDto
{
 public int Id{get;set;}
 public string FirstName{get;set;}
 public string LastName{get;set;}
 public string FullName{get;set;}
}

然后选择

db.Persons.Select(p => new PresonDto
                           {
                               Id = p.Id,
                               FirstName = p.firstname,
                               LastName = p.lastname,
                               FullName = p.firstname ?? "" + " " + p.lastname ?? ""
                           });

修改

如果你不想使用dtos并想要更多或更少的通用方法,我在sql查询期间没有看到任何填充对象属性的方法。并选择一些模型到新模型()中,重新分配所有字段并不是一个好主意。

所以我唯一可以提供的方法是使用一些容器来存储你想要选择的原始模型和其他字段。

public class ItemAdditionalPropertyContainer<TModel>
{
    public TModel Item { get; set; }
    public string PropertyValue { get; set; }
}

public static IQueryable<ItemAdditionalPropertyContainer<TModel>> GetItemsWithAdditionalProperty<TModel>(
    IQueryable<TModel> items,
    Expression<Func<TModel, string>> additionalPropertySelector)
{
    Expression<Func<TModel, ItemAdditionalPropertyContainer<TModel>>> expr = 
        item => new ItemAdditionalPropertyContainer<TModel> 
            { 
                Item = item, 
                PropertyValue = additionalPropertySelector.Compile()(item)
            };
    return items.Select(expr.ExpandExpressions() );
}

但是你必须使用一些表达式扩展器。 expr.ExpandExpressions()为了让LINQ以正确的方式编译它。

我用过这个(git link)。这是nuget package。或者你可以自己实现它。