2013-07-15 8 views
1

나는 사용자 정보 (상속 코드)에 대한 IVeryBasicData를 구현하는 인터페이스 IBasicData 있습니다인터페이스 구현 인터페이스 4

public interface IBasicData:IVeryBasicData 
{ 
    byte[] Password { get; set; } 
    string Email { get; set; } 
} 

public interface IVeryBasicData:IUser 
{ 
    string Name { get; set; } 
    string UserId { get; set; } 
    string Description { get; set; } 
    string Url { get; set; } 
} 
public interface IUser 
{ 
    DateTime CreationTime { get; set; } 
    string PartitionKey { get; set; } 
    string RowKey { get; set; } 
} 

그럼 내가를 반환 UsersDataSource에서하는 방법 GetUsers이를 IQueryable<IBasicData>,이 IQueryable을 뷰의 모델로 사용할 수 있기를 원합니다. 하지만 그것을하려고 할 때 Exception이 발생합니다 : 예를 들어 @Hml.DisplayNameFor(model => model.UserId)으로 호출 할 때 속성을 찾을 수 없습니다.

그래서,이 솔루션 왔어요 :

foreach (var user in usersDataSource.GetUsers()) 
     { 
      var addUser = new UserViewModel() 
      { 
       CreationTime = user.CreationTime, 
       Description = user.Description, 
       Email = user.Email, 
       Name = user.Name, 
       PartitionKey = user.PartitionKey, 
       Password = user.Password, 
       RowKey = user.RowKey, 
       Url = user.Url, 
       UserId = user.UserId 
      }; 
      usersViewModel.Add(addUser); 
     } 
     return View(usersViewModel); 

UserViewModel는 IBasicData를 구현하는 클래스입니다. 이 작품은 오히려 못생긴 나에게 보인다. IQuaryable<IBasicData>을 View 모델로 사용할 수있는 더 좋은 방법이 있습니까?

+2

컨트롤러에서보기를 반환하기 전에 IQueryable <>을 사용하고 데이터 컨텍스트를 삭제했기 때문에 예외가 발생했다고 가정합니다. IEnumberable <>을 반환하고 반환 된 엔터티 집합에서 .ToList()를 호출하려고 했습니까? – Tommy

+0

나는 당신이 말하는 것을 꽤 얻지 못한다고 생각합니다 (이 분야에서 거의 새로운 것). 현재 내 컨트롤러는 다음과 같습니다. public ActionResult Index() { return view (users.GetUsers(). ToList()); } – danielrozo

+0

IQueryable <>은 아직 데이터베이스에서 검색되었거나 검색되지 않은 개체 집합입니다. EF 및 LINQ에서는 실제로 데이터를 열거하거나 목록과 같은 개체에 캐스팅 할 때까지 실행이 지연됩니다. 귀하의 경우에는 HTML을 렌더링하기 시작할 때까지 쿼리가 지연 될 가능성이 가장 높았지만 그 당시에는 데이터베이스에 대한 연결을 이미 닫았다가 폐기했습니다. 따라서 예외가 발생합니다. 아래의 내 대답은 MVC에서 뷰 렌더링을 시작하기 전에 .ToList()를 호출하여 데이터가 있는지 확인하는 것입니다. – Tommy

답변

1

먼저 모델 선언에서 IEnumerable을 사용하도록보기를 업데이트하십시오.

보기

@model IEnumerable<IBasicData> 

@{foreach(var user in Model){ 
    //I don't know how you are wanting to render out the data...example only 
    @user.Email<br/> 
    @user.Name 
}} 

그런 다음 컨트롤러에서, 다음을 수행 할 수 있어야한다 :

var modelData = usersDataSource.GetUsers().Select(user=>new UserViewModel{ 
       CreationTime = user.CreationTime, 
       Description = user.Description, 
       Email = user.Email, 
       Name = user.Name, 
       PartitionKey = user.PartitionKey, 
       Password = user.Password, 
       RowKey = user.RowKey, 
       Url = user.Url, 
       UserId = user.UserId 
      }).ToList(); 
return View(modelData); 

.ToList을 (호출)는 쿼리가 즉시 실행하고 검색됩니다 데이터를보기로 이동하기 전에

+0

고마워요. 토미. 이 솔루션은 Exception :'표현식 user.CreationTime을 가진 gpmData.User.UserViewModel의 인스턴스를 생성하거나 초기화하지 않습니다 .'를 던졌습니다. 그리고 수동 속성 할당을 사용하여 하나의 엔티티를 다른 엔티티로 복사합니다 . 내가 원하는 것은 이것을 피하는 것입니다. – danielrozo

+0

이것이 당신과 관련이 있는지 궁금합니다. View 모델과 같은 구체적인 클래스가 아닌 인터페이스입니다. 뷰 모델 클래스 (속성 만있는 클래스), 필요한 경우 상속이있는 구체적인 클래스의 인터페이스는 사용한 적이 없습니다. MVVM 배경에서 왔습니까? 빠른 검색에서 인터페이스를 사용하는 것처럼 보이기 때문에 인터페이스를위한 구체적인 클래스를 작성해야합니다. 이렇게하면 오류를 설명 할 수 있습니다. – Tommy

+0

한 개체를 다른 개체로 복사하는 경우 개체 모델을 뷰 모델에 바인딩하려는 경우 AutoMapper를 항상 살펴볼 수 있습니다. http://automapper.org/ – Tommy

0

IBasicData 인터페이스의 개체에서 작동하는 모델 바인더는 암호 및 전자 메일 속성에 대해서만 알고 있기 때문에 예외가 throw되지 않습니까? 모델 바인더는 아마도 리플렉션을 사용하며 기본 인터페이스를 선택하지 않을 수도 있습니다 ?

예를 들어, 마이크로 소프트 .NET 프레임 워크는 객체 지향 원칙 우수한 지원을 제공에도 불구하고, DefaultModelBinder이 추상 기본에 클래스를 바인딩 는 지원을 제공하지 않습니다 견적 This article on MSDN Magazine 강조 광산

에서

및 인터페이스.

내가 당신의 ViewModel 클래스는 단지 명시 적으로 3 인터페이스를 구현하고 (이 클래스의 인스턴스로 실제 EF 엔티티에서 투사를 유지하도록하는 것이 좋습니다 것 정직하게하려면, 즉 usersDataSource.Select (U => 새로운 UserViewModel {...}); 다음과 여기에 올바른 접근 방식처럼 소리가 나지 않는다 @model IEnumerable을

인터페이스 상속과 뷰에 바인딩, 나는 당신이 가지고있는 투사 코드에 대해 걱정하지 것이다, 그것은 꽤 정상 EF 레이어와 프리젠 테이션 레이어 (보기)간에 좋은 분리를 제공한다는 점을 명심하십시오.

동의합니다. IEnumerable에 Tommy와 함께 e; 일단 EF 계층을 벗어나면 IEnumerable은 데이터를 즉시 구체화하고 가능한 한 빨리 데이터베이스 연결을 닫습니다.

+0

필자가 이해하는 한, 이것은 내가 한 일이다 : 인터페이스와 리플렉션을 구현하는 클래스. 예외는 매우 명확합니다. 인터페이스에서 더 깊숙히 들어가서 속성을 추론 할 수는 없습니다. 리플렉션은 생성자 중 하나에서 수행되었습니다. – danielrozo

+0

예.하지만 원래 코드는 @ 모델을 지정합니다. IEnumerable 은 IEnumerable 과 같지 않습니다. 이전에는 IBasic 속성 만 있고, 후자는 모두 있습니다. ViewModel의 3 가지 인터페이스 구현은 어떤 이유로 인해 이러한 객체를 컨트롤러/뷰로 인터페이스별로 전달해야하는 경우에만 존재해야합니다. 컨트롤러에서 해당 투영을 실행하는 경우 인터페이스가 중복됩니다! –

+0

업데이트하는 것을 잊어 버렸습니다. Tommy 's ans 이후 IEnumerable 을 가지고 있습니다. 프로젝션이 UserViewModel에서 실행되고 있는데, 여전히 중복입니까? – danielrozo