我有以下方法在调用时接受DataTime
参数,并根据传递的日期返回记录。
方法:
public static void GetVehicleByReleasedDate(DateTime parameter)
{
using (EntityDataModel context = new EntityDataModel())
{
var query =
from vehicle in context.Catalog
where vehicle.ReleaseDate >= parameter.Date
select new
{
VehicleMake = vehicle.VehicleMake,
ManufactureID = vehicle.ManufactureID,
ManufactureDate = vehicle.ManufacturedDate,
VehicleIdentificationNumber = vehicle.VehicleIdentificationNumber
};
foreach (var vehicle in query)
{
Console.WriteLine("Format and write result to Console",
vehicle.ManufactureID,
vehicle.ManufactureDate,
vehicle.VehicleIdentificationNumber,
vehicle.VehicleMake);
}
}
}
除了上述内容之外,我还需要返回一个IQueryable
对象或目录,以便我可以在方法之外执行查询。
像这样:
public static IQueryable<Catalog> GetVehicleByReleasedDate()
{
using (EntityDataModel context = new EntityDataModel())
{
return context.Catalog;
}
}
然后调用这样的方法:
static void Main(string[] args)
{
var query = from vehicle in GetVehicleByReleasedDate()
where vehicle.ReleaseDate >= DateTime.Now
select new
{
VehicleMake = vehicle.VehicleMake,
ManufactureID = vehicle.ManufactureID,
ManufactureDate = vehicle.ManufacturedDate,
VehicleIdentificationNumber = vehicle.VehicleIdentificationNumber
};
foreach (var vehicle in query)
{
Console.WriteLine("{0} {1:d} {2} {3}",
vehicle.ManufactureID,
vehicle.ManufactureDate,
vehicle.VehicleIdentificationNumber,
vehicle.VehicleMake);
}
Console.ReadKey();
}
正如您所知,我收到错误,因为GetVehicleByReleasedDate()
中的使用处理了上下文。
错误讯息:
The operation cannot be completed because the DbContext has been disposed.
如何编写此代码以便我可以在Context
处置之前使用返回类型从另一个方法向该方法传递查询?
更新
这是EntityDataModel类:
public partial class EntityDataModel : DbContext
{
public EntityDataModel()
: base("name=EntityDataModel")
{
}
public virtual DbSet<Catalog> Catalog { get; set; }
public virtual DbSet<Model> Model { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Catalog>()
.Property(e => e.VehicleIdentificationNumber)
.IsFixedLength();
}
}
最后,这是目录模型。
[Table("Automobile.Catalog")]
public partial class Catalog
{
[Key]
public long ManufactureID { get; set; }
[Required]
[StringLength(100)]
public string VehicleMake { get; set; }
[Required]
[StringLength(17)]
public string VehicleIdentificationNumber { get; set; }
[Column(TypeName = "date")]
public DateTime ManufacturedDate { get; set; }
[Column(TypeName = "date")]
public DateTime ReleaseDate { get; set; }
}
答案 0 :(得分:1)
IQueryable界面非常懒惰。它只在真正需要时才评估查询。我建议在查询结尾处使用.ToList()来实现它:
var query =
(from vehicle in context.Catalog
where vehicle.ReleaseDate >= parameter.Date
select new
{
VehicleMake = vehicle.VehicleMake,
ManufactureID = vehicle.ManufactureID,
ManufactureDate = vehicle.ManufacturedDate,
VehicleIdentificationNumber = vehicle.VehicleIdentificationNumber
}).ToList();
否则,由于您的using
语句,当IQueryable最终评估查询时,上下文已经被处理掉了。使用ToList()
可以强制查询实现,结果将存储在内存中。
更新:为了让答案更加完整,正如Gert Arnold指出:
// YourStaticClass.cs
public static IEnumerable<Catalog> GetVehicleByReleasedDate(DateTime parameter)
{
using (var context = new EntityDataModel())
{
return context.Catalog
.Where(x => parameter.Date <= x.ReleaseDate)
.ToList();
}
}
// Main.cs
static void Main(string[] args)
{
var vehicles = YourStaticClass.GetVehicleByReleasedDate(DateTime.Today);
foreach (var vehicle in vehicles)
{
Console.WriteLine("{0} {1:d} {2} {3}",
vehicle.ManufactureID,
vehicle.ManufactureDate,
vehicle.VehicleIdentificationNumber,
vehicle.VehicleMake);
}
Console.ReadKey();
}
像这样,当上下文仍然“未被曝光”时,您将实现查询。您可以将数据吐出到您需要的任何地方并进行处理。
答案 1 :(得分:1)
更新:
如果您希望保持与EF和静态方法的耦合,请尝试这样的回调设置:
public static void GetVehicleByReleasedDate(Func<DbSet<Catalog>, IQueryable<dynamic>> query, Action<IQueryable<dynamic>> useQuery)
{
using (EntityDataModel context = new EntityDataModel())
{
useQuery(query(context.Catalog));
}
}
public static T GetVehicleByReleasedDate<T>(Func<DbSet<Catalog>, IQueryable<dynamic>> query, Func<IQueryable<dynamic>, T> useQuery)
{
using (EntityDataModel context = new EntityDataModel())
{
return useQuery(query(context.Catalog));
}
}
并将其称为:
static void Main(string[] args)
{
GetVehicleByReleasedDate
(
catalog=>
from vehicle in catalog
where vehicle.ReleaseDate >= DateTime.Now
select new
{
VehicleMake = vehicle.VehicleMake,
ManufactureID = vehicle.ManufactureID,
ManufactureDate = vehicle.ManufacturedDate,
VehicleIdentificationNumber = vehicle.VehicleIdentificationNumber
},
query=>
{
foreach (var vehicle in query)
{
Console.WriteLine("{0} {1:d} {2} {3}",
vehicle.ManufactureID,
vehicle.ManufactureDate,
vehicle.VehicleIdentificationNumber,
vehicle.VehicleMake);
}
}
);
Console.ReadKey();
}
更新2 :
如果您对与EF脱钩感兴趣,请尝试以下方法:
public class IEntityRepository : IDisposable
{
IQueryable<Catalog> GetVehicleByReleasedDate();
}
public class EFEntityRepository : IEntityRepository
{
private EntityDataModel context = new EntityDataModel():
public IQueryable<Catalog> GetVehicleByReleasedDate()
{
return this.context.Catalog;
}
public void Dispose()
{
this.context.Dispose();
this.context = null;
}
}
public class Consumer
{
private Func<IEntityRepository> createRepository;
public Consumer(Func<IEntityRepository> createRepository) { this.createRepository = createRepository; }
public void OutputData()
{
using (var repository = this.createRepository())
{
var query = from vehicle in repository.GetVehicleByReleasedDate()
where vehicle.ReleaseDate >= DateTime.Now
select new
{
VehicleMake = vehicle.VehicleMake,
ManufactureID = vehicle.ManufactureID,
ManufactureDate = vehicle.ManufacturedDate,
VehicleIdentificationNumber = vehicle.VehicleIdentificationNumber
};
foreach (var vehicle in query)
{
Console.WriteLine("{0} {1:d} {2} {3}",
vehicle.ManufactureID,
vehicle.ManufactureDate,
vehicle.VehicleIdentificationNumber,
vehicle.VehicleMake);
}
}
}
}
public class Program
{
static void Main(string[] args)
{
var consumer = new Consumer(()=>new EFEntityRepository());
consumer.OutputData();
}
}
答案 2 :(得分:1)
GetVehicleByReleaseDate可以将上下文作为参数,因此它不会控制上下文的生命周期,只是控制模型在返回之前的操作方式。我强烈建议仍然保持上下文的生命周期。
public static IQueryable<Catalog> GetVehicleByReleasedDate(EntityDataModel context)
{
//Do whatever data manipulations you need here.
}
但是,如果GetVehcileByReleaseDate除了从上下文中返回实体之外没有做什么,你甚至需要吗?
您检查了存储库模式吗?您可以为存储库对象的生命周期创建上下文。有点像这样:
http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx
答案 3 :(得分:0)
您需要一个依赖注入库来为您控制。看看Autofac及其生命周期。我将它用于Web应用程序,并将创建的对象的生命周期(例如DbContext)设置为整个HTTP请求的生命周期,并且工作正常。
http://docs.autofac.org/en/stable/lifetime/index.html http://www.codeproject.com/Articles/25380/Dependency-Injection-with-Autofac#scope