I have repository generic where I do method as Get,Update,Insert.
I get a data from table in data base I use this method.
public IEnumerable<typeEntity> Get<typeEntity>(Expression<Func<typeEntity, bool>> newObjectEntity,int page, int rowsByPage) where typeEntity : class
{
List<typeEntity> Result = null;
Result = Context.Set<typeEntity>().Where(newObjectEntity).OrderBy(m => true).Skip<typeEntity>(5 * (page - 1)).Take<typeEntity>(rowsByPage).ToList<typeEntity>();
return Result;
}
I when get data only a one table this is my code:
var collecProducts = repository.Get<Products>(c => true);
My problem is when I want get two tablet How I do this?. I find this code but is very slow.
var collecProducts = repository.Get<Products>(c => true);
var collecCategory = repository.Get<Category>(c => true);
var collectProductToCategory = (from p in collecProducts
join c in collecCategory on p.idCategory equals c.idCategory).ToList();
The problem this code is that get all data de products and category and I want from SQL Server only data necessary for example as join TSQL.
select p.idProducts from products p join category c on p.idCategory = c.idCategory
In conclusion How I could get data use join since repository generyc.
The solution you found is slow because the repository method is materializing/executing the query immediately instead of allowing deferred execution to occur. Try removing the ".ToList()" from the query within the repository method:
public IEnumerable<typeEntity> Get<typeEntity>(Expression<Func<typeEntity, bool>> newObjectEntity,int page, int rowsByPage) where typeEntity : class
{
IEnumerable<typeEntity> Result = null;
Result = Context.Set<typeEntity>().Where(newObjectEntity).OrderBy(m => true).Skip<typeEntity>(5 * (page - 1)).Take<typeEntity>(rowsByPage);
return Result;
}
This will allow you to compose and construct higher order queries without pulling the whole table into memory immediately.
I find a form get this result for example Product and Category in repository Generic through include.
public IEnumerable<typeEntity> Get<typeEntity>(Expression<Func<typeEntity, bool>> newObjectEntity,int page, int rowsByPage, string include) where typeEntity : class
{
List<typeEntity> Result = null;
Result = Context.Set<typeEntity>().Where(newObjectEntity).include(include).OrderBy(m => true).Skip<typeEntity>(5 * (page - 1)).Take<typeEntity>(rowsByPage).ToList<typeEntity>();
return Result;
}
With include you can string for example Product->Category and get this object.
Related
I am trying to build up a mongo query, I very nearly have it working in Linq (95% there), but it looks like there is an unfortunate missing ability in the Linq provider to do the equivalent of an Intersect(coll).Any() or in Mongo parlance AnyIn()
I understand that if I use the fluent library with some builders I can build up a filter that will give me an AnyIn() - but what I am missing is how could I build up the whole query, the initial filter, the aggregation, projection and the filter at the end?
This is a very close approximation of my Linq query - this works exactly as required as long as I am not trying to compare collection membership in the filter
public List<MyResult> ListMyResults(Expression<Func<MyResult, bool>> filter, int skip, int take)
{
// Limit to tennants on main Entity being queried
var ents = ApplyDataRestrictions(db.GetCollection<Entity>("entities").AsQueryAble());
var children = db.GetCollection<Child>("children").AsQueryable();
var chickens = db.GetCollection<Chicken>("chickens").AsQueryable();
// Join a couple collections for their counts
var result = from ent in ents
join c in children on ent.Id equals c.EntityId into kids
join ck in chickens on ent.Id equals ck.EntityId into birds
// Project the results into a MyResult
select new MyResult
{
Id = ent.Id,
AProperty = ent.AProperty,
SomeCollection = ent.SomeCollection,
SomeOtherCollectionTagsMaybe = ent.SomeOtherCollectionTagsMaybe,
TotalKids = kids.Count(),
TotalChickens = birds.Count()
};
if(filter != null)
{
// Apply the filter that was built up from criteria on the MyResults data shape
result = result.Where(filter);
}
result = result.Skip(skip).Take(take);
return result.ToList()
}
public IQueryable<Entity> ApplyDataRestrictions(IQueryable<Entity> query)
{
... restrict results to only those with my tennant id ...
}
Actually it turns out that the same behavior can be achieved without Query Builder and AnyIn. Having IQueryable interface you can try .Any() with Contains() as inner predicate
var inMemoryList = new List<int>() { 3, 4, 5 };
var q = from doc in Col.AsQueryable()
where doc.Collection.Any(x => inMemoryList.Contains(x))
select doc;
or
var q2 = Col.AsQueryable().Where(x => x.Collection.Any(y => inMemoryList.Contains(y)));
So currently i am writing a specific SQL function to get a specific row from a specific table.
However, I have dozens of tables, and noticed that I am writing these same 'get row' repository functions each time I make a new table.
Is it possible to write a generic function that works for every table, in this case to get a specific row?
Current (Example)
public Purchase GetPurchase(long purchaseId)
{
using (var db = new DbContext(_connStringKey))
{
var result = (from p in db.Purchases
where p.PurchaseId.Equals(purchaseId)
select p).FirstOrDefault();
return result;
}
}
Generic Example (To give you an idea)
public Object GenericGet (string tableName, string rowName, long rowId)
{
using (var db = new DbContext(_connStringKey))
{
var result = (from p in db.tableName
where p.rowName.Equals(rowId)
select p).FirstOrDefault();
return result;
}
}
You can do it using reflection but it is not a good approach. Instead of this, you could try something using the generics aspects of the language, and make sure what you want, for sample:
public T Get<T>(Expression<Func<T, bool>> filter)
where T : class
{
T result;
using (var db = new DbContext(_connStringKey))
{
result = db.Set<T>().FirstOrDefault(filter);
}
return result;
}
Remember that the T must be a reference type, so, define a constraint for class
Then, you could try this:
var product = Get<Product>(p => p.Name == "Something");
var supplier = Get<Supplier>(p => p.Sector == "Manufacturing");
I am a little weak in LINQ to SQL so will try to explain my problem.
I have a method as follows (simplified to explain it better):
public static List<ic_ProductData> GetCompleteSimilarProductsWithApplyButton(InfoChoiceAdminDataContext db)
{
var products = (from
p in db.ic_ProductDatas
join proddef in db.ic_ProductDefs on p.ProductDefId equals proddef.ProductDefId
select p
).ToList();
return products;
}
ic_ProductData and ic_ProductDefs are tables in my database
The ic_ProductData class contains a manually created property as:
public ic_ProductDef RelatedProductDef { get; set; }
I want to modify the above LINQ to SQL query so that I can populate this property.
Please note I do not want another call to the database.
Also there are a lot of properties in ic_ProductData so I want to avoid mapping each and every property
Something to the effect of the following (obviously the below is wrong):
public static List<ic_ProductData> GetCompleteSimilarProductsWithApplyButton(InfoChoiceAdminDataContext db)
{
var products = (from
p in db.ic_ProductDatas
join proddef in db.ic_ProductDefs on p.ProductDefId equals proddef.ProductDefId
//trying to change here
select new ic_ProductData
{
//do something with p here so that all the properties of new object gets filled
// avoid mapping of properties here
RelatedProductDef = proddef
}
).ToList();
return products;
}
With my limited knowledge I am stuck here.
Please help!
Thanks in advance!
You can do something like this:
var query = (from p in db.ic_ProductDatas
join proddef in db.ic_ProductDefs on p.ProductDefId equals proddef.ProductDefId
select new
{
ProductData = p,
Def = proddef
}).ToList();
List<ic_ProductData> products = new List<ic_ProductData>();
foreach( var product in query)
{
product.ProductData.RelatedProductDef = product.Def;
products.Add(product);
}
Basicly, you first need to do the one query to the database, this returns an anonymous type containing both your product and its Def.
Finally, you loop (in memory, no db-calls!) over these, creating your final objects with their RelatedProductDef properties populated.
I have ths function to query a set of records from the DB:
public IQueryable<PointTransactionViewModel> GetPointTransactions(int UserID)
{
return
(
from PointTransaction p in entities.PointTransaction
join ActivityLog a in entities.ActivityLog
on p.TransactionID equals a.TransactionID
where p.UserID == UserID
select new PointTransactionViewModel
{
ID = p.TransactionID,
Balance = p.Balance,
Points = p.Amount,
RelatedActivityID = a.ID,
When = p.When,
Sender = p.SenderUserInfo.CompleteName
}
);
}
I wish to add an additional cause, like this
var entries = GetPointTransaction(1);
return entries.OrderbyDescending.Where( x => x.When >= start && w.When <= end).
( x => x.When);
However, I seem to need to create a new query from the existing one for this to work. But, I have seem this work before without creating a new query, in the code snippet before:
public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize)
{
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = source.Count();
TotalPages = (int)Math.Ceiling(TotalCount / (double)PageSize);
this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
}
Does the code above somehow doesn't need a new query to be created for the IQueryable source object? Was a temporary object created?
Edit
It's strange, but to get it to work I have to do the following:
IQueryable<ActivityLogEntry> log = activityRepo.GetPointTransaction(userID).
Where(x => x.PointsEarned == 50);
return log.ToList();
The following will not work:
var log = = activityRepo.GetPointTransaction(userID);
log.Where( x => x.PointsEarned == 50);
return log.ToList();
There is no error message, just that the where clause seems to be ignored (it is also returning all data which PointsEarned is not 50)
Your entries is of IQueryable type, that's enough and you can add any number of clauses before fetching the data, e.g. before calling the ToList() function.
It doesn't execute the SQL code, just an expression tree will be created until you fetch the whole data with one of the existing methods (again, e.g. the ToList() function).
var query = context.Where(x=>x.id == test);
query = query.Where(anotherCondition1);
query = query.Where(anotherCondition2);
...
var result = query.ToList();
it's equal to
var result = context.Where(x=>x.id == test)
.Where(anotherCondition1)
.Where(anotherCondition2)
....
.ToList()
This is called deferred execution, for more details see the MSDN blog post on LINQ and Deferred Execution.
You do need to create a new object. IQueryable is immutable. Don't worry this is how you are supposed to do it. This is how the queries are formed internally. All the extension methods like "Where" don't actually change the object. They just return a new one.
The code that you claim works should not work. The method doesn't even have a type.
i mean you can write this sample :
opportunites = from opp in oppDC.Opportunities
join org in oppDC.Organizations on opp.OrganizationID equals org.OrgnizationID
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
if(condition)
{
opportunites = opportunites.Where(opp => opp.Title.StartsWith(title));
}
//------Other Condition you need
if(!String.IsNullOrEmpty(title))
{
opportunites = opportunites.Where(.....);
}
if(!String.IsNullOrEmpty(name))
{
opportunites = opportunites.Where(.....);
}
As others have pointed out, you do not need a new object. Your syntax for OrderByDescending is wrong though, you need to specify the key selector.
var entries = GetPointTransaction(1);
return entries.Where(x => x.When >= start && w.When <= end).OrderbyDescending(x => x.When);
im trying to return a list in a web service method with the results of some db queries.
My Query is:
var Address = (from table in Model.Table where *-some conditions and join clause-* select Address).Firstordefault();
var Phone =(from table in Model.Table where *-some conditions and join clause-* select Phone).FirstOrDefault();
Web Service Method:
[WebMethod]
public List< x> ShowDetails(*input parameters*)
{
List< x> list = new List<x>();
list.Add(Address);
list.Add(Phone);
return list;
}
My question is how can i define the List< x> elements with my query results?
I don't see the reason to use a list here. Simple solution is create a custom class to save both result:
public class X
{
public Address Address{get;set;}
public Phone Pnone {get;set;}
}
And then you can do the following:
[WebMethod]
public X ShowDetails(*input parameters*)
{
var address = Model.Addresses.FirstorDefault(some conditions);
var phone = Model.Phones.FirstorDefault(some conditions);
return new X{Address=address, Phone=phone};
}
Now I see that you mention you are also joining tables probably to apply some conditions. I suggest you instead of that you use navigation properties,eg:
var address = Model.Addresses.FirstorDefault(a=>a.State.StateId==9);
That query is going to do the join for you once it's translated to sql.