gpt4 book ai didi

.net - 自定义 IQueryable

转载 作者:行者123 更新时间:2023-12-02 04:19:22 24 4
gpt4 key购买 nike

我正在尝试自定义应用程序的实体,以使它们具有引用加载它们的 DataContext 的属性。

我认为最好的方法是以某种方式创建一个实现 IQueryable 的类并在其 GetEnumerator 方法中设置实体 datacontext 属性。

我的问题是,如何在我的 IQueryable 实现中使用 Linq to SQL 使用的提供程序和表达式,这样我就不必自己实现它们了?

顺便说一句:对于我的场景,还有其他方法吗?

看看下面的代码:

public partial class Product: IEntityBase  
{

public Product()
{
_DataContext = new SampleDataContext();
}

private long _Id;
[Column(Storage="_Id", AutoSync=AutoSync.OnInsert, DbType="BigInt NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public long Id
{
get{ return _Id; }
set{ _Id = value; }
}

private string _Name;
[Column(Storage="_Name", DbType="NVarChar(MAX) NOT NULL", CanBeNull=false
public string Name
{
get{ return _Name; }
set{ _Name = value; }
}

private SampleDataContext _DataContext;

//This is the property extending the Product class and should be set when this class is being returned
//by IQueryable<T>.GetEnumerator()
public SampleDataContext DataContext
{
get{ return _Name; }
set{ _Name = value; }
}

public MyQueryable<Product> GetProducts()
{
MyQueryable<Product> result = from p in context.Products
where {Some Conditions 1}
select p;
result.DataContext = _DataContext;
return result;
}

public void SomeMethod()
{
//This query will not actually set the DataCotnext property.
//And the generated sql query is something like:
//SELECT * FROM Products WHERE {Some Conditions 1} AND {Some Conditions 2}
var products = GetProducts().Where( {Some Conditions 2} );

//Now that the GetEnumerator() is called the DataContext property of the products
//will be set.
foreach( var item in products )
{
item.Name = "Test Name";
item.DataContext.SubmitChanges();
}
}
}

public MyQueryable<T>: IQueryable<T>
where T: class, IEntityBase
{
//
//Implementation of IQueryable which is my question
//

public IEnumerator<T> GetEnumerator()
{
foreach( var item in Provider.GetEnumerator<T>() )
{
item.DataContext = this.DataContext;
yield return item;
}
}

public SampleDataContext DataContext{ get; set; }
}

public interface IEntityBase
{
SampleDataContext DataContext{ get; set; };
}

更新

我自己找到了答案。这是显示我如何做到这一点的示例代码。
public MyQueryable<T, TContext>: IQueryable<T> 
where T: class, IEntityBase
where TContext: DataContext, new()
{

public MyQueryable<T>(TContext context, IQueryable<T> baseIQueryable)
{
if( baseIQueryable == null )
throw new ArgumentNullException("baseIQueryable");

this.Provider = baseIQueryable.Provider;
this.Expression = baseIQueryable.Expression;

this.DataContext = context;
}

public IEnumerator<T> GetEnumerator()
{
var enumerator = Provider.Execute<IEnumerable<T>>(Expression);
foreach( var item in enumerator )
{
item.DataContext = this.DataContext ?? new TContext();
yield return item;
}
}

IEnumerator IEnumerable.GetEnumerator()
{
var enumerator = Provider.Execute<IEnumerable>(Expression);
foreach( var item in enumerator )
{
((IEntityBase<TContext>)item).DataContext = this.DataContext;
yield return item;
}
}

//
//Other implementations...
//
public SampleDataContext DataContext{ get; set; }
}

public partial class Product: IEntityBase
{
public MyQueryable<Product> GetProducts()
{
var result = from p in context.Products
where {Some Conditions 1}
select p;
return new MyQueryable<typeof(Product), DataContext>(this.DataContext, result);
}
}

最佳答案

我想不出一个简单的方法来做到这一点。您不能在不破坏可组合性的情况下注入(inject) LINQ-to-SQL 管道的中间。最简单的方法是通过 LINQ-to-Objects 作为最后一步:

public IEnumerable<Product> GetProducts() 
{
IQueryable<Product> result = from p in context.Products
where {Some Conditions 1}
select p;
return result.AsEnumerable().Select( x => {
x.SomeProp = context;
return x;
});
}

但请注意,这破坏了可组合性——下游的一切都是 LINQ-to-Objects。

由于您的实体有一个通用的基类/接口(interface),因此可以将其包装在扩展方法中以实现非常相似的行为(但更好地重用):
   return result.AssociateWith(context);

有类似的东西:
public static IEnumerable<T> AssociateWith<T>(
this IEnumerable<T> source,
DataContext context)
where T : IEntityBase
{
foreach(T item in source)
{
item.DataContext = context;
yield return item;
}
}

关于.net - 自定义 IQueryable<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/486947/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com