익명 형식을 생성하는 동적 선택기식이 있습니다. 이 객체에 LINQ에서 잘 작동,하지만 엔티티에 LINQ에, 그것은 예외 :동적 선택기 Linq To Entities
시도
만 매개 변수가없는 생성자와 초기화가 엔티티에 LINQ에서 지원되는 1
NotSupportedException이.
Expression<Func<User, T>> DynamicSelect<T>(T obj, ParameterExpression userParam)
{
var newExpression = Expression.New(
typeof(T).GetConstructor(typeof(T).GenericTypeArguments),
userParam,
Expression.Constant("X"),
Expression.Constant("Y")
);
return Expression.Lambda<Func<User, T>>(newExpression, userParam);
}
var userParam = Expression.Parameter(typeof(User), "u");
var obj = new { User = new User(), Address = string.Empty, Fax = string.Empty };
var arr = context.Set<T>()
.Select(DynamicSelect(obj, userParam))
.ToArray();
시도 2 , 나는 사용자 정의 유형을 작성하는 경우, 그것은 일하고,하지만 각 개체에 대한 추가 사용자 지정 형식을 만들지 않고이 도우미 방법을 다시 사용하려는 때문에 내가 싶지 않아, I 소비자를 기반으로 유형을 전달할 수 있기를 원합니다.
public class Container
{
public User User { get; set; }
public string Address { get; set; }
public string Fax { get; set; }
}
Expression<Func<User, T>> DynamicSelect<T>(T obj, ParameterExpression userParam)
{
var initExpression = Expression.MemberInit(
Expression.New(typeof(T)),
Expression.Bind(typeof(T).GetProperty("User"), userParam),
Expression.Bind(typeof(T).GetProperty("Address"), Expression.Constant("X")),
Expression.Bind(typeof(T).GetProperty("Fax"), Expression.Constant("Y"))
);
return Expression.Lambda<Func<User, T>>(initExpression, userParam);
}
var userParam = Expression.Parameter(typeof(User), "u");
var arr = context.Set<T>()
.Select(DynamicSelect<Container>(null, userParam))
.ToArray();
시도 3
, 나는 또한Tuple<User, string, string>
를 사용하여 시도,하지만 너무 지원 아니에요.
NotSupportedException이
방법 'System.Tuple`3를 인식하지 못하는 엔티티에 LINQ [사용자, 선택 System.String, 선택 System.String] 만들기 [사용자, 문자열, 문자열 (사용자, 시스템 .String, System.String) ' 메서드이며이 메서드는 저장소 식으로 변환 할 수 없습니다.
Expression<Func<User, T>> DynamicSelect<T>(T obj, ParameterExpression userParam)
{
var createExpression = Expression.Call(
typeof(Tuple),
"Create",
typeof(T).GenericTypeArguments,
userParam,
Expression.Constant("X"),
Expression.Constant("Y"));
return Expression.Lambda<Func<User, T>>(createExpression, userParam);
}
var userParam = Expression.Parameter(typeof(User), "u");
var arr = context.Set<User>()
.Select(DynamicSelect<Tuple<User, string, string>>(null, userParam))
.ToArray();
이 도와주세요.
나는 각각의 소비자에게 특정 구현을하지 않고 어떤 소비자 (사용자, 고객, 동료 등)이 도우미 메서드를 다시 사용하려고했다
업데이트합니다.
클래스 구조는 다음과 같습니다.
public class User
{
public int Id { get; set; }
public string UserName { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string CompanyName { get; set; }
public virtual ICollection<Contact> Contacts { get; set; }
}
public class Contact
{
public int Id { get; set; }
public string Type { get; set; }
public string Content { get; set; }
}
public class UserDto
{
public int Id { get; set; }
public string UserName { get; set; }
public ContactDto Contact { get; set; }
}
public class CustomerDto
{
public int Id { get; set; }
public string CompanyName { get; set; }
public ContactDto Contact { get; set; }
}
public class ContactDto
{
public string Email { get; set; }
public string Address { get; set; }
public string Fax { get; set; }
// other contact informations
}
그리고 나는 각 소비자마다 다를 수있는 많은 연락처가 있습니다. , Invoke
방법은 표현 LINQ에서 지원되지 않기 때문에 그것은 오류가 발생합니다
var users = context.Set<User>()
.Select(x => new UserDto
{
Id = x.Id,
UserName = x.UserName,
Contact = new ContactDto
{
Email = GetContactExpression("Email").Compile()(x)
}
})
.ToArray();
:
var users = context.Set<User>()
.Select(x => new UserDto
{
Id = x.Id,
UserName = x.UserName,
Contact = new ContactDto
{
Email = x.Contacts.Where(c => c.Type == "Email").Select(c => c.Value).FirstOrDefault()
}
})
.ToArray();
var customers = context.Set<Customer>()
.Select(x => new CustomerDto
{
Id = x.Id,
CompanyName = x.CompanyName,
Contact = new ContactDto
{
Address = x.Contacts.Where(c => c.Type == "Address").Select(c => c.Value).FirstOrDefault(),
Fax = x.Contacts.Where(c => c.Type == "Fax").Select(c => c.Value).FirstOrDefault(),
}
})
.ToArray();
그리고 표현에 리팩토링,하지만 내가 좋아하는 방법 내에서 직접 사용할 수 없습니다 그래서 내가 전체 Select
표현을 리팩토링해야하지만 일반 (User
은 UserName
을 가지고 있지만 CompanyName
을 가진 Customer
및 기타 정보가 있어야 함)이 문제가 해결 된 후에도 접촉 유형을 전달할 필요가 있습니다.
var obj = new { User = new User(), Email = "" };
var users = context.Set<User>()
.Select(x => DynamicSelect(obj))
.Select(x => new UserDto
{
Id = x.User.Id,
UserName = x.User.UserName,
Contact = new ContactDto
{
Email = x.Email
}
})
.ToArray();
표현식 생성기의 예상 동작이 다른 익명 형식에 어떤 영향을 미치는지 정의해야한다고 생각합니다. "Address"속성을 항상 기대할 수 있습니다. 예를 들어 "X"로 설정할 수 있습니까? – StriplingWarrior
@StriplingWarrior, 일부 엔티티는'Contact' 테이블과 일대 다 관계를 가지고 있습니다. 상수 "X"는'user.Contacts.Where (c => c.Type ==)를 대체하기 위해 만든 다른 selector 표현식으로 대체 될 것입니다. "Address") Select (x => x.Text) .FirstOrDefault()', 상수를 사용하여 문제를 단순화 했으므로 예상 결과에는 항상 Address, Phone, Email과 같은 속성이 포함됩니다. 이 도우미가 주체 유형 (사용자, 고객 등)의 매개 변수와 추출 할 연락처의 유형을 받아 들일 수 있기를 바랍니다. 하지만 지금은'u => new {User = u}'를 표현식으로 대체해야합니다. – tsuta
먼저 구체화하십시오. 이후에 동적 선택을 사용 하시겠습니까? (동적 선택 <...> (...)) ' – B0Andrew