I'm trying to create app that implements MVP pattern using WinForms.
Wherein I'm also using EF+CodeFirst+Linq.
On the VIEW there is DataGridView control, that need filling a data. The VIEW call a method SELECT() of PRESENTER class, which in turn call a method SELECT() of MODEL class.
How to transfer the data from Data Base to VIEW via PRESENTER?
I'm trying to use return but it not work because i'm using the USING block.
internal void Select()
{
using (GoodsContext context = new GoodsContext())
{
var items = from Items in context.Goods
select Items;
}
}
Quite interesting question. Of course one can materialize the query and return it as IEnumerable, but I was wondering what is the way to return it as IQueryable, to allow further filtering/sorting etc. The only way I see is to not dispose the DbContext (apparently the returned queryable keeps reference to it), but is it safe? Then I've googled and found this Do I always have to call Dispose() on my DbContext objects? Nope. The explanation inside sounds reasonable to me, and we already have a disposable object (Task) that we are not supposed to Dispose.
Shortly, you can remove the using statement and return the IQueryable.
Change return type of Select method to List<Good>
Then "materialize" result to the List of data, and you will not depend on the DataContext
internal List<Good> Select()
{
using (GoodsContext context = new GoodsContext())
{
return context.Goods.Select(items => items).ToList();
}
}
You should change type of method Select from void to IEnumerable<Good> to be able to return something. Also use .ToList to materialize result to a List:
internal IEnumerable<Good> Select()
{
using (GoodsContext context = new GoodsContext())
{
var items = (from Items in context.Goods
select Items).ToList();
return items;
}
}
Related
I have a HttpGet endpoint, and it should return a collection of transfers, I'm using my Entity Transfer to do that
but I'm trying to change to use my CommandResponse(or viewmodel) GetTransferResponse, and I don't know how to use my var transfer in my CommandResponse
I already use it when it's only one transfer, but with a collection, I Don't know how create the constructor in this case, I think it's going to looks like this, but it's going to be a collection:
my repository:
You can use extension methods to convert ICollection<Transfer> to ICollection<GetTransferResponse>.
Make sure to include:
using System.Linq;
Update your GetAll method to:
public ICollection<GetTransferResponse> GetAll()
{
var transfer = _repo.GetAll()
.Select(x => new GetTransferResponse(x))
.ToList();
return transfer;
}
I'm learning entity framework and hitting a wall. Here is my code:
public IOrderedEnumerable<ArchiveProcess> getHistory()
{
using (ArchiveVMADDatabase.ArchiveDatabaseModel dataContext = new ArchiveDatabaseModel())
{
var query = (from history in dataContext.ArchiveProcess.AsNoTracking()
orderby history.ArchiveBegin descending
select history).Take(10).ToList();
return query as IOrderedEnumerable<ArchiveProcess>;
}
}
When I step through this code, query is a List<ArchiveProcess> containing my ten desired results. However, as soon as I exit the method and the context is disposed of, query becomes null. How can I avoid this? I tried doing this instead:
select new ArchiveProcess
{
ArchiveBegin = history.ArchiveBegin,
ArchiveEnd = history.ArchiveEnd,
DeploysHistoryCount = history.DeploysHistoryCount,
MachinesHistory = history.MachinesHistory,
ScriptHistory = history.ScriptHistory
}
But then I received a NotSupportedException. Why does entity framework delete my precious entities as soon as the context is disposed of and how do I tell it to stop?
I think there are several ways to avoid this but in general you should know precisely how long you want your context to live. In general it's better to have the using statement wrapped through the entire method.
In order to avoid the garbage collection you can do something like this: set the object in memory and then add value to that object.
List<ArchiveProcess> query;
using (ArchiveVMADDatabase.ArchiveDatabaseModel dataContext = new ArchiveDatabaseModel())
{
query = (from history in dataContext.ArchiveProcess.AsNoTracking()
orderby history.ArchiveBegin descending
select history).Take(10).ToList();
return query; /// you do not really need to all enumerable as IOrderedEnumerable<ArchiveProcess>;
}
query as IOrderedEnumerable<ArchiveProcess>;
query is a List<ArchiveProcess>, as returns null when you try use it to cast something to an interface it doesn't implement. List<ArchiveProcess> is not an IOrderedEnumerable<ArchiveProcess> so query as IOrderedEnumerable<ArchiveProcess> is null.
The only thing that IOrderedEnumerable<T> does that IEnumerable<T> doesn't do, is implement CreateOrderedEnumerable<TKey>, which can be called directly or through ThenBy and ThenByDescending, so you can add a secondary sort on the enumerable that only affects items considered equivalent by the earlier sort.
If you don't use CreateOrderedEnumerable() either directly or through ThenBy() or ThenByDescending() then change to not attempt to use it:
public IEnumerable<ArchiveProcess> getHistory()
{
using (ArchiveVMADDatabase.ArchiveDatabaseModel dataContext = new ArchiveDatabaseModel())
{
return (from history in dataContext.ArchiveProcess.AsNoTracking()
orderby history.ArchiveBegin descending
select history).Take(10).ToList();
}
}
Otherwise reapply the ordering, so that ThenBy etc. can be used with it:
public IOrderedEnumerable<ArchiveProcess> getHistory()
{
using (ArchiveVMADDatabase.ArchiveDatabaseModel dataContext = new ArchiveDatabaseModel())
{
return (from history in dataContext.ArchiveProcess.AsNoTracking()
orderby history.ArchiveBegin descending
select history).Take(10).ToList().OrderBy(h => h.ArchiveBegin);
}
}
However this adds a bit more overhead, so don't do it if you don't need it.
Remember, IOrderedEnumerable<T> is not just an ordered enumerable (all enumerables are in some order, however arbitrary), it's an ordered enumerable that has knowledge about the way it which it is ordered so as to provide for secondary sorting. If you don't need that then you don't need IOrderedEnumerable<T>.
using (ArchiveVMADDatabase.ArchiveDatabaseModel dataContext = new ArchiveDatabaseModel())
{
var query = dataContext.ArchiveProcess.AsNoTracking().Take(10).OrderBy(o=> o.ArchiveBegin);
return query;
}
Most of my question is in the title: Does WPF DataGrid Implicitly Convert IEnumerable<X> ItemsSource to List<x>?
I have a WPF, using MVVM, etc. ViewModel property is defined as ...
private IEnumerable<Plan> _PlanListItems;
public IEnumerable<Plan> PlanListItems
{
get { return _PlanListItems; }
protected set { RaiseAndSetIfChanged(ref _PlanListItems, value); }
}
// ...
// in some method
OpenPlanItems = await service.GetAllPlansAsync();
In service ...
public IEnumerable<Plan> GetAllPlans()
{
using (MyEntities ent = new MyEntities())
{
return (from a in ent.DbPlans select a)
.AsEnumerable()
.Select(o => o.Convert()); // Does some stuff to convert DbPlan entity into Plan class
}
}
public async Task<IEnumerable<Plan>> GetAllPlansAsync()
{
return await Task.Run(() => GetAllPlans());
}
In XAML ...
<DataGrid ItemsSource="{Binding PlanListItems}" ...>
This throws an exception: The operation cannot be completed because the DbContext has been disposed error. Another question indicates a cause could be due to late execution on the IEnumerable object (i.e. trying to enumerate after the context has been disposed).
Additionally, I have similar code that has a .ToList() conversion inside a method similar to GetAllPlans(). Something like this, but not the actual code:
public List<Plan> GetAllPlans()
{
using (MyEntities ent = new MyEntities())
{
return (from a in ent.DbPlans select a)
.AsEnumerable()
.Select(o => o.Convert()).ToList(); // Does some stuff to convert ...
}
}
It turned out to be a slow method (>5 seconds). When I removed the .ToList() conversion, it dropped the time to <0.2 seconds, but the inefficiency returned (and almost the exact same duration) when I bind the result to a DataGrid.
This leads me to believe that WPF DataGrid implicitly converts IEnumerable bound items to a List as part of the binding process. Is that true? And if so, is there a way to avoid the implicit conversion?
The reason your IEnumerable<T> service takes < 0.2 seconds to return is because it isn't actually returning data: it is returning more of 'how to get the data, when you're actually interested in it'. It will only actually give you the data when you iterate over it or otherwise access it. This will give you the DbContext has been disposed of error you had, if the client code tries to make use of that 'how to get the data' outside of the scope of the context.
This is why when you have .ToList() on your service it takes longer: because it is actually returning data. Real data you can really use on the client without worrying about the scope of the context.
The DataGrid just needs its ItemsSource collection to implement the IEnumerable interface, so it can enumerate over the items as and when it needs to. It isn't "converting things to a list" per se, it is just enumerating the collection.
i am using this in my data layer
public static IQueryable<Permission> ListAll()
{
using (InventorySystemEntities context = new InventorySystemEntities(new ConfigurationManager().ConnectionString))
{
IQueryable<Permission> result = context.Permissions;
return result;
}
}
it should put all rows inside the result variable. however doing something like this, and it will result to context has been disposed..
permissionList = PermissionModel.ListAll();
chkListGeneral.DataSource = permissionList.Where(p => p.Parent == "General");
is there a way to filter the IQueryable without a context?
The connection is accessible only as long as the context that wraps it. Your method returns IQueryable, so the filter is trying to be "translated" to a DB query, but the underlying query provider no longer exists. You either need to specify the where condition while the context still exists, or force eager load (e.g. by calling ToList() on the result variable), return IEnumerable and filter the results in memory.
I'm using EF 4.1 and I'm trying to enumerate a company list for a grid. I have two options in the current project: select all companies from the DbContext (Entities) and load them into an object from a non-anonymous type (let's say EmpresaGrid) or select all companies into anonymous type objects with the same structure like Empresa (which is the entity I'm selecting from).
The first option (creating a model class for that) would require a little more work, but can be, eventually, more readable. Still, I'm not sure about that. The second option is what I'm using right now.
So, first question: it's better to create a model class only for displaying data or use anonymous type? Doing a direct select is out of question: a SELECT * is too big and that might make everything damn slow (I guess). So selection into another type creates a custom query with only the needed fields.
Using the second option (anonymous type), I have this code (simplified version):
public static IEnumerable<object> Grid()
{
Entities db = new Entities();
var empresas = db.Empresas
.Select(e => new
{
Cgc = e.Cgc, // PK
(...)
Address = new
{
AddressLine = e.EnderecoSede.AddressLine,
(...)
}
},
Contato = e.Contato,
(...)
})
.ToList();
return empresas;
}
The anonymous type I'm creating has around 40 lines of code, so it's kinda big, but it recreates part of the Empresa class struct (since the grid is waiting for a Empresa object). Anyway, I have a problem with the data format. For example, I would like to format the Cgc property using a custom string format. I have a public method for this, FormataCgc. This method receives a string and returns it formatted using some internal conditions.
So, my problem is how to that. For example, I have tried this:
var empresas = db.Empresas
.Select(e => new
{
Cgc = FormataCgc(e.Cgc),
}
But that doesn't work because FormataCgc cannot be translated into SQL (and I don't want to convert it). I also tried this:
var empresas = db.Empresas
.Select(e => new
{
(...)
}
.ToList();
foreach (var e in empresas) {
e.Cgc = FormataCgc(e.Cgc);
}
But it cannot be done since anonymous types have only read-only properties.
So, my second question is: how exactly can I do that? I need to change the data after selecting it, but using anonymous types? I've done a little research, and the best thing I've found was this: Calling a custom method in LINQ query. In that solution, Ladislav suggested doing a second select from the IEnumerable, but since the grid is excepting Empresa I cannot do that (I need to change or add properties, not encapsulate them).
I'm not sure if I was clear enough, but feel free to ask any questions. Also, the grid I'm currently using is a Telerik ASP.NET MVC Grid, which receives a IEnumerable (where T is a class) as model data and them iterates each object, doing its magic.
Since you're already converting this into an IEnumerable<T>, you can do the custom formatting as you stream the results in the client. Do your db.Select, and then convert to the appropriate format afterwards, ie:
var empresas = db.Empresas
.Select(e => new
{
(...)
})
.ToList();
foreach (var e in empresas) {
yield return new {
Cgc = FormataCgc(e.Cgc),
// Copy other properties here, as needed...
};
}
That being said, I'd personally recommend making a custom class, and not return an anonymous type. Your conversion would then be:
foreach (var e in empresas) {
yield return new YourClass(FormataCgc(e.Cgc), ...); // Construct as needed
}
This will dramatically improve the usability of this method, as you will have proper, named access to your properties from the caller of the method.
I think the solution to both of your questions is to create a model class. Sure it is a little bit more work up front, but it will allow you greater flexibility in the long run. Your custom model class can then handle the formatting for you.
public class EmpresaGridModel
{
public string Cgc { get; set; }
public string CgcFormatted
{
return FormataCgc(this.Cgc);
}
//properties for the other fields will have to be created as well obviously
}
Your telerik grid can then bind directly to the CgcFormatted property