I Made a new notMapped class "BuyingHistory", that have some property (not all) of two database tables
how to fill this class with entity? I made the conditions, but how do I select the properties to a list? (I know how to do it for one property but not for a list)
IQueryable<BuyingHistory> _buyingList =
_db.Orders
.Join(_db.EventPages
,o => o.EventID
,e => e.ID
,(o, e) => new { orders = o, events = e })
.Where(o => o.orders.UserID == LS.CurrentUser.ID)
.Select( // I don't know how to continue
it's work in this way bellow, but how can I do it in one command like the example above
var _List =
_db.Orders
.Join(_db.EventPages
, o => o.EventID
, e => e.ID
, (o, e) => new { orders = o, events = e })
.Where(o => o.orders.UserID == LS.CurrentUser.ID).ToList();
List<BuyingHistory> _buyingList = new List<BuyingHistory>();
foreach (var item in _List)
{
_buyingList.Add(new BuyingHistory()
{
CreatedDate = item.orders.CreatedDate,
EventName = item.events.Title,
NumberOfTickets = item.orders.TicketNumber,
OrderID = item.orders.ID,
Status = item.orders.Status.ToString(),
Total = item.orders.TicketNumber
});
}
I'd use query syntax to begin with, and then do the query like so:
from ord in _db.Orders
join evt in _db.EventPages on ord.EventID equals evt.ID
where ord.UserID == LS.CurrentUser.ID
select new BuyingHistory
{
CreatedDate = ord.CreatedDate,
EventName = evt.Title,
NumberOfTickets = ord.TicketNumber,
OrderID = ord.ID,
Status = ord.Status.ToString(),
Total = ord.TicketNumber
})
If you have EF version 6 the ToString() won't throw exceptions. If not, you have to change the type of BuyingHistory.Status into the type coming from the database.
I am using LinqKit.dll to do Linq To Entity in my application, as follow :
qry = _articleRepo.GetItemsByCulture(Thread.CurrentThread.CurrentCulture.Name)
.AsExpandable().Where(x => x.Approved && isInCategory(x.CategoryID, category.CategoryID));
Func<string, int, bool> isInCategory = (x, y) =>
{
IQueryable<string> list = x.Split(',').AsQueryable();
//Except
//x.Except(_);
return list.Any(z => z == y.ToString());
};
it gives me error :
System.InvalidCastException: Unable to cast object of type
'System.Linq.Expressions.FieldExpression' to type
'System.Linq.Expressions.LambdaExpression'.
but removing isInCategory(x.CategoryID, category.CategoryID) causes the application to run without problem.
Would please help me ?
Ok, after looking at the code in comments, I can suggest following:
Replace string CategoryID on Article to public virtual ICollection<Category> Categories { get; set; }, so EF will create a foreign key. Then, in order to get articles, that are in particular category, you can use code similar to the following:
var articlesInCategory = context.Articles
.Where(x => x.Language == Thread.CurrentThread.CurrentCulture.Name)
.Where(x => x.Approved && x.Categories.Any(c => c.CategoryID == c1.CategoryID)).ToList();
And when you want to create new articles, you should use something like:
var c1 = context.Categories.OrderBy(c => c.Title).First();
var c2 = context.Categories.OrderBy(c => c.Title).Skip(1).First();
context.Articles.Add(new Article { Categories = new Collection<Category> { c1, c2 } });
context.SaveChanges();
I need to implement a version of CombineLatest (I'll call it WithLatest here) that calls the selector for every item on the left and the latest item on the right. It shouldn't push for items on the right changing only.
I think whether this is built Observable.Create or a combination of existing extensions is not particularly important; I'll be making this a "boxed" extension method either way.
Example
var left = new Subject<int>();
var right = new Subject<int>();
left.WithLatest(right, (l,r) => l + " " + r).Dump();
left.OnNext(1); // <1>
left.OnNext(2); // <2>
right.OnNext(1); // <3>
right.OnNext(2); // <4>
left.OnNext(3); // <5>
should yield
2 1
3 2
Edit: The logic of my example goes:
Left becomes populated with 1. Right is empty, no values pushed.
Left becomes updated with 2 (it forgets the previous value). Right is still empty, so nothing is pushed.
Right becomes populated with 1, so Left = 2 (the latest value), Right = 1 is pushed. Up to this point, there is no difference between WithLatest and CombineLatest
Right is updated -- nothing is pushed. This is what's different
Left is updated with 3, so Left = 3, Right = 2 (the latest value) is pushed.
It's been suggested that I try:
var lr = right.ObserveOn(Scheduler.TaskPool).Latest();
left.Select(l => l + " " + lr.First()).Dump();
but this blocks on the current thread for my test.
You can do this using existing operators.
Func<int, int, string> selector = (l, r) => l + " " + r;
var query = right.Publish(rs => left.Zip(rs.MostRecent(0), selector).SkipUntil(rs));
Publish ensures we only ever subscribe to right once and share the subscription among all subscribers to rs.
MostRecent turns an IObservable<T> into an IEnumerable<T> that always yields the most recently emitted value from the source observable.
Zip between IObservable<T> and IEnumerable<U> emits a value each time the observable emits a value.
SkipUntil skips the pairs (l, r) which occur before right ever emits a value.
I also had the same need for a CombineLatest which "pushes only for the left".
I made the solution an "overload" of Observable.Sample, because that's what the method does:
It samples a source (right) with a sampler (left), with the additional capability of providing a resultSelector (like in CombineLatest).
public static IObservable<TResult> Sample<TSource, TSample, TResult>(
this IObservable<TSource> source,
IObservable<TSample> sampler,
Func<TSource, TSample, TResult> resultSelector)
{
var multiSampler = sampler.Publish().RefCount();
return source.CombineLatest(multiSampler, resultSelector).Sample(multiSampler);
}
Based on the solution picked by the post author I think there's an even simpler solution utilizing DistinctUntilChanged:
public static IObservable<TResult> CombineLatestOnLeft<TLeft, TRight, TResult>(this IObservable<TLeft> leftSource, IObservable<TRight> rightSource, Func<TLeft, TRight, TResult> selector) {
return leftSource
.Select<TLeft, Tuple<TLeft, int>>(Tuple.Create<TLeft, int>)
.CombineLatest(rightSource,
(l, r) => new { Index = l.Item2, Left = l.Item1, Right = r })
.DistinctUntilChanged(x => x.Index)
.Select(x => selector(x.Left, x.Right));
}
or even
public static IObservable<TResult> CombineLatestOnLeft<TLeft, TRight, TResult>(this IObservable<TLeft> leftSource, IObservable<TRight> rightSource, Func<TLeft, TRight, TResult> selector) {
return leftSource
.CombineLatest(rightSource,
(l, r) => new { Left = l, Right = r })
.DistinctUntilChanged(x => x.Left)
.Select(x => selector(x.Left, x.Right));
}
if you only care about distinct values of leftSource
On latest System.Reactive, we can use WithLatestFrom extension method.
left.WithLatestFrom(right, (l, r) => l + " " + r).Dump();
The result would be below correctly.
3 2
Here's the hacky way using Create - didn't actually build it, mea culpa if it doesn't actually work :)
public static IObservable<TRet> WithLatest<TLeft, TRight, TRet>(
this IObservable<TLeft> lhs,
IObservable<TRight> rhs,
Func<TLeft, TRight, TRet> sel)
{
return Observable.Create<TRet>(subj => {
bool rhsSet = false;
bool deaded = false;
var latestRhs = default(TRight);
Action onDeaded = null;
var rhsDisp = rhs.Subscribe(
x => { latestRhs = x; rhsSet = true; },
ex => { subj.OnError(ex); onDeaded(); });
var lhsDisp = lhs
.Where(_ => deaded == false && rhsSet == true)
.Subscribe(
x => subj.OnNext(sel(x, latestRhs)),
ex => { subj.OnError(ex); onDeaded(); },
() => { subj.OnCompleted(); onDeaded(); });
onDeaded = () => {
deaded = true;
if (lhsDisp != null) {
lhsDisp.Dispose();
lhsDisp = null;
}
if (rhsDisp != null) {
rhsDisp.Dispose();
rhsDisp = null;
}
};
return onDeaded;
});
}
I made a RX operator for project today that does this.
Here's my solutions:
public static IObservable<Tuple<TSource, TTarget>> JoinLeftSoft<TSource, TTarget>(
this IObservable<TSource> source, IObservable<TTarget> right)
{
return source
.Select(x => new Tuple<object, TSource>(new object(), x))
.CombineLatest(right, (l, r) => new Tuple<object, TSource, TTarget>(l.Item1, l.Item2, r))
.DistinctUntilChanged(t => t.Item1)
.Select(t => new Tuple<TSource, TTarget>(t.Item2, t.Item3));
}
I Use entity Framework 4.
I would like to be able to create a function that return an Expression func that will be use in a lambda expression.
var ViewModel = _db.Suppliers.Select(model => new {
model,SupType = model.SupplierType.SupplierTypeTexts.Where( st => st.LangID == 1)
});
I would like to make this call like that
var ViewModel = _db.Suppliers.Select(model => new {
model,SupType = model.SupplierType.GetText()
});
My Partial class is:
public partial class SupplierType
{
public Expression<Func<SupplierTypeText, bool>> GetText()
{
return p => p.LangID == 1;
}
How can i perform this.
Easy. For example, Let's assume you have a Product table that is mapped to Products EntitySet in your context, now you want to pass a predicate and select a Product:
Expression<Func<Product, bool>> GetPredicate(int id) {
return (p => p.ProductID == id);
}
You can call GetPredicate() with a Product ID to filter based on that:
var query = ctx.Products.Where(GetPredicate(1)).First();
The point really is that you can always pass a Lambda Expression to where an Expression<T> is needed.
EDIT:
You should change your code like this:
var ViewModel = _db.Suppliers.Select(model => new {
model,
SupType = model.SupplierType.SupplierTypeTexts.Where(GetText())
});
public Expression<Func<SupplierTypeText, bool>> GetText() {
return (stt => stt.LangID == 1);
}
If you want to dynamically create compiled Expression at runtime (as opposed to ones hardcoded against a particular data model at compile time) you need to use the static methods on the Expression class.
I know currently the compiler is not liking this statement. Getting Error
Cannot convert lambda expression to delegate type 'System.Func<MyData.Models.SomeModels,bool>' because some of the return types in the block are not implicitly convertible to the delegate return type
My Statement I'm passing to my Repository Class
var qry = repositoryClass.Find(c => c.Categories.Where(d => d.CategoryParentID == typeID));
Repository Class Find Method
public IEnumerable<SomeModels> Find(Func<SomeModels, bool> exp)
{
return (from col in _db.SomeModels where exp select col);
}
To work with EF you need an Expression<...>, applied (as a predicate) with Where:
public IEnumerable<SomeModels> Find(Expression<Func<SomeModels, bool>> exp)
{
return _db.SomeModels.Where(exp);
}
You'd then call that as:
var qry = repositoryClass.Find(c => c.CategoryParentID == typeID);
The lambda is then translated into an Expression<...>.
If your setup is more complex, please clarify.
I just added a method in my Repository Class
public IEnumerable<Models> GetByCategory(int categoryID)
{
var qry = _db.ModelCategories.Where(p => p.CategoryID == categoryID).First();
qry.Models.Load();
return qry.Models;
}
I'm guessing because it needs to be loaded this is the best way to go.