LINQ에서 SQL 클래스를 상속하고 LINQ 쿼리의 결과를 캐스팅합니다.
-
20-08-2019 - |
문제
기본 엔티티를 여러 가지 다른 것 (예 : 직원, 차량 등)으로 확장 해야하는 응용 프로그램을 작성하고 있습니다. 디자인은 엔티티 테이블과 유형 별 값이있는 두 번째 테이블이있는 것과 같습니다. (직원에게는 ID 번호가 있지만 차량에는 등록 번호가 있습니다.
데이터 컨텍스트에서 생성 된 클래스 엔티티에서 물려 받았지만 저장소의 캐스팅에 문제가 있습니다. 이 작업을 수행하는 올바른 방법은 무엇입니까?
public class cAccountEmployee : cAccountEntity
{
public string id_number
{
get
{
try
{
return this.cAccountEntityValues.Single(e => e.type == 1).value;
}
catch (Exception)
{
return "";
}
}
set
{
try
{
this.cAccountEntityValues.Single(e => e.type == 1).value = value;
}
catch (Exception)
{
this.cAccountEntityValues.Add(new cAccountEntityValue()
{
accountentity_id = this.id,
cAccountEntity = this,
type = 1,
value = value
});
}
}
}
}
그런 다음 내 저장소에서 (아무것도 상속하지 않음)
public IEnumerable<cAccountEmployee> All(int accountholder_id)
{
return db.cAccountEntities.Where(e => e.accountholder_id == accountholder_id).OrderBy(a => a.name).Cast<cAccountEmployee>();
}
public cAccountEmployee Single(int id)
{
return db.cAccountEntities.Single(a => a.id == id) as cAccountEmployee;
}
캐스트는 단일 방법으로 실패하므로 NULL이됩니다. 기본 클래스에서 또는 기본 클래스에서 명시 적 또는 암시 적 연산자를 정의 할 수 없다는 것은 내 이해입니까? 기본 클래스 LINQ 결과를 어떻게 상속 된 직원 클래스에 올리도록하고, 여전히 DB 상태를 유지하여 변경 사항을 제출할 수 있습니까?
해결책
LINQ-to-SQL을 사용하면 상속이 작동 할 수있는 두 가지 방법이 있습니다.
- 단일 테이블 위의 판별 자 (데이터가 동질하지 않기 때문에 적합하지 않음)
- 기본 클래스 / 멀티 테이블 (DBML에서는 지원되지 않는 것이 아닙니다. 수업을 수동으로 작성하는 경우에만)
LINQ-to-SQL은 다중 테이블 상속을 지원하지 않습니다 (즉, 여러 테이블의 데이터가있는 단일 객체). 엔티티 프레임 워크는하지만 더 복잡합니다. 너는 사용한다 .Cast<T>
그리고 .OfType<T>
하위 유형을 기준으로 EF에서 캐스트/필터로
당신은 다음을보고 싶을 수도 있습니다.
- ID를 기반으로 쿼리 (결합
GetTable<T>()
) - DBML에서 기본 클래스를 지정합니다
여기서 기본 클래스의 목적은 무엇입니까? 동작이 추가되면 DBML을 편집하여 모든 엔티티에 공통 기본 클래스를 지정할 수 있습니다. 가지고 있다면 데이터 속성 그러면 까다로워집니다.
개인적으로, 나는 단순히 이런 식으로 그렇게하지 않을 것입니다 ... 나는 다른 유형에 대한 별도의 클래스를 유지하고 유형 당 별도의 테이블을 사용하여 데이터 컨텍스트를 올바르게 사용할 것입니다.
public IEnumerable<Employee> All(int accountholder_id)
{
return db.Employees.Where(e => e.accountholder_id == accountholder_id)
.OrderBy(a => a.name);
}
public Employee Single(int id)
{
return db.Employees.Single(a => a.id == id);
}
그래서 - 당신은 무엇을 명확히 할 수 있습니까? cAccountEntity
여기에?
다른 팁
입력에 감사드립니다. 몇 가지 제안을 살펴 보겠습니다 ...
계정 엔티티의 아이디어는 현재 사이트가 직원 만 처리하면되지만 앞으로는 차량 등을 시스템에 추가하기를 원할 수도 있고 시스템은 엔터티에 비용을 할당하는 데 사용되므로 직원은 직원이 차량과 동일하게 처리했습니다.
아이디어는 직원과 차량이 DB 등을 참조하기 위해 동일하게 처리해야하지만 이에 대한 정보가 약간 다른 정보가 필요하다는 것입니다. 나중에 추가 유형을 추가하기를 원하지만 DB를 업그레이드 할 필요없이 복잡한 디자인입니다.
그러나 내 코드에서는 일반 엔티티 유형이 아닌 직원에 대해 이야기하고 싶습니다 (MVC 앱에서 컨트롤러,보기 등을 훨씬 쉽게보기). 기본에서 파생 클래스로 사용자 정의 캐스팅을 공급할 수 없으므로 물속을 건너 뛰고 다음 솔루션을 대신 사용했습니다. 조금 더 번거롭지 만 작동합니다 ... 누군가 더 나은 방법을 볼 수 있는지 알려주세요.
public class cAccountEmployee
{
private cAccountEntity entity;
public int id
{
get
{
return this.entity.id;
}
set
{
this.entity.id = value;
}
}
public string name
{
get
{
return this.entity.name;
}
set
{
this.entity.name = value;
}
}
public int accountholder_id
{
get
{
return this.entity.accountholder_id;
}
set
{
this.entity.accountholder_id = value;
}
}
public System.Data.Linq.EntitySet<cAccountEntityValue> cAccountEntityValues
{
get
{
return this.entity.cAccountEntityValues;
}
}
public cAccountHolder cAccountHolder
{
get
{
return this.entity.cAccountHolder;
}
}
public cAccountEmployee()
{
this.entity = new cAccountEntity();
}
public cAccountEmployee(cAccountEntity entity)
{
this.entity = entity;
}
public string id_number
{
get
{
try
{
return this.entity.cAccountEntityValues.Single(e => e.type == 1).value;
}
catch (Exception)
{
return "";
}
}
set
{
try
{
this.entity.cAccountEntityValues.Single(e => e.type == 1).value = value;
}
catch (Exception)
{
this.entity.cAccountEntityValues.Add(new cAccountEntityValue()
{
accountentity_id = this.id,
cAccountEntity = this.entity,
type = 1,
value = value
});
}
}
}
}
//In the repository
public cAccountEmployee Single(int id)
{
return new cAccountEmployee(db.cAccountEntities.Single(a => a.id == id));
}
기본 클래스 LINQ 결과를 상속받은 직원 클래스에 올리도록하려면 어떻게해야합니까?
그것은 업 캐스트가 아니라 다운 캐스트입니다.
캐스팅이나 인스턴스 유형 대 참조 유형을 이해하지 못한다고 생각합니다.
public class Animal { }
public class Zebra : Animal { }
public class Zoo
{
public void ShowZebraCast()
{
Animal a = new Animal();
Zebra z = (Zebra)a;
}
}
System.InvalidCastException : '동물'유형의 대상을 캐스트 할 수 없습니다.
같은 방식으로, 당신은 직원 참조를 사용하기 위해 다운 캐스트 할 수없는 엔티티 인스턴스가 있습니다.
유형을 변환 할 수 있지만 변환 방법을 제공해야합니다.
public partial class Animal { }
public class Zebra : Animal { }
//in another file
public partial class Animal{
public Zebra ToZebra(){
return new Zebra() { //set Zebra properties here.
};
}
}
public class Zoo
{
public void ShowZebraConvert()
{
Animal a = new Animal();
Zebra z = a.ToZebra();
}
}