many to many 속성에서 반환 할 수있는 IManyToManySet<TEntity>
인터페이스를 만들고 쿼리 삽입 및 삭제 기능을 사용하여 ManyToManySet<TSource, TCross, TDestination>
구현을 만들 수 있습니다.
인터페이스는 다음과 같이 보일 수 있습니다 :
public interface IManyToManySet<TEntity> : IEnumerable<TEntity>
where TEntity : class
{
int Count { get; }
void Add(TEntity entity);
bool Remove(TEntity entity);
void AddRange(IEnumerable<TEntity> collection);
}
그리고 구현은 다음과 같습니다
당신은이 구현에 몇 가지를 제공해야
public class ManyToManySet<TSource, TCross, TDestination>
: IManyToManySet<TDestination>, IEnumerable<TDestination>
where TDestination : class
where TSource : class
where TCross : class
{
private TSource source;
private EntitySet<TCross> crossSet;
private Func<TCross, TDestination> destinationSelector;
private Func<TSource, TDestination, TCross> crossFactory;
public ManyToManySet(TSource source,
EntitySet<TCross> crossSet,
Func<TCross, TDestination> destinationSelector,
Func<TSource, TDestination, TCross> crossFactory)
{
this.source = source;
this.crossSet = crossSet;
this.destinationSelector = destinationSelector;
this.crossFactory = crossFactory;
}
public int Count
{
get { return this.crossSet.Count; }
}
public void Add(TDestination entity)
{
var newEntity = this.crossFactory(this.source, entity);
this.crossSet.Add(newEntity);
}
public bool Remove(TDestination entity)
{
var existingEntity = (
from c in this.crossSet
where this.destinationSelector(c) == entity
select c)
.SingleOrDefault();
if (existingEntity != null)
{
return this.crossSet.Remove(existingEntity);
}
return false;
}
public void AddRange(IEnumerable<TDestination> collection)
{
foreach (var entity in collection)
{
this.Add(entity);
}
}
public IEnumerator<TDestination> GetEnumerator()
{
return this.crossSet.Select(this.destinationSelector)
.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
:
TSource
인스턴스는 속성을 정의하는 엔터티를 다시 가리 킵니다.
- 크로스 테이블을 정의하는 엔티티 목록을 가리키는
EntitySet<TCross>
입니다.
TCross
을 TDestination
으로 변환 할 수있는 프로젝션 함수입니다.
TSource
및 TDestination
을 기반으로 새 TCross
을 만들 수있는 팩토리 함수입니다. (Product
및 Order
사용) 실제 예를 들어이 번역
, 당신에게 Order
기업에 대한 다음과 같은 속성을 줄 것이다 다음 Product
기업에 대한
private IManyToManySet<Product> products;
public IManyToManySet<Product> Products
{
get
{
if (this.products != null)
{
this.products = new ManyToManySet<Order, OrderProduct, Product>(
this, this.OrderProducts, op => op.Product,
(o, p) => new OrderProduct { Order = o, Product = p });
}
return this.products;
}
}
그리고 다음 등록 정보 :
private IManyToManySet<Order> orders;
public IManyToManySet<Order> Orders
{
get
{
if (this.orders == null)
{
this.orders = new ManyToManySet<Product, OrderProduct, Order>(
this, this.OrderProducts, op => op.Order,
(p, o) => new OrderProduct { Order = o, Product = p });
}
return this.orders;
}
}
을
IManyToManySet<T>
인터페이스는 실제로 ManyToMany<TSource, TCross, TDestination>
을 반환 할 수 있기 때문에 중복되어 있습니다. 인터페이스는 TSource
및 TCross
형식 인수를 숨기므로이 속성을 사용자가 좀 더 쉽게 읽을 수 있습니다.
이 구현에는 LINQ to SQL의 EntitySet<T>
과 같은 로딩 동작이 있습니다. 이 함수를 사용하면 메모리에 전체 개체 집합이로드됩니다. 컬렉션에 where
또는 First
을 사용하는 EntitySet<T>
처럼 데이터베이스에서 전체 컬렉션을로드합니다. 당신은 그 사실을 알고 있어야합니다.
그러나 중요한 차이점은 LINQ to SQL이 LINQ 쿼리 내에서 EntitySet<T>
속성을 인식한다는 것입니다. IManyToManySet<T>
을 LINQ 쿼리 내에 포함하면 비참하게 실패합니다.
이 정보가 도움이되기를 바랍니다.
한가지 내가 약간의 문제가 있었는데 그 관계는 행을 제거하는 대신 크로스 테이블에서 외래 키를 null로 null을 시도 했으므로 관계를 제거하는 것이 었습니다. 부모 항목 엔티티 집합에서 제거 될 때 행이 삭제되도록하는 연관에 대해 DeleteOnNull을 설정할 수 있음을 알았습니다. –
나는 계획이 함께 할 때 그것을 사랑한다! – Steven