I'm just getting started using QueryDSL with Spring Data JPA. I have a class where I'm storing all of my predicates, so that in my service methods, I can just call findAll() or findOne() on my repositories by passing in the boolean expression. Here's an example:
Predicate class method:
public static BooleanExpression byCode(String code) {
return QHeading.heading.code.eq(code);
}
Service class method:
public Iterable<Heading> getByCode(final String code) {
return headingRepository.findAll(byCode(code));
}
This works fine, but in the case where one heading is the child of another heading, I'd like to reuse the same method from my predicate class, just wrapping it in another method that returns the parent heading, rather than the child that matches the boolean expression. However, I'm having a bit of trouble figuring out the correct way to do this.
So, it would be something like this:
Predicate methods:
public static BooleanExpression byCode(String code) {
return QHeading.heading.code.eq(code);
}
public static BooleanExpression byChildCode(String code) {
QHeading.heading.childHeadings.eq(byCode(code));
}
Service method:
public Iterable<Heading> getByChildCode(final String code) {
return headingRepository.findAll(byChildCode(code));
}
Obviously, the eq() method doesn't work, but is there a way to accomplish this, or is there a different way I should be going about this entirely?
You can either do it like this
public static BooleanExpression byCode(String code) {
return QHeading.heading.code.eq(code);
}
public static BooleanExpression byChildCode(String code) {
return QHeading.heading.childHeadings.any().code.eq(code);
}
or if you want more code reusal:
private static BooleanExpression byCode(QHeading heading, String code) {
return heading.code.eq(code);
}
public static BooleanExpression byCode(String code) {
return byCode(QHeading.heading, code);
}
public static BooleanExpression byChildCode(String code) {
return byCode(QHeading.heading.childHeadings.any(), code);
}
Related
I am looking to see if there is away to force the AsNoTracking in a static class ? I know there are other ways of doing it but, this is used all over the application. This is just basic example. SearchTest().Search()
private IQueryable<SomeModel> SearchTest()
{
return (from t in _dbContext.test
select new SomeModel()
{
a.test1
}).AsQueryable();
}
public static async Task<SomeModel> Search<T>(this IQueryable<T> query)
{
return new SomeModel(){ Count=await query.CountAsync()};
}
In my application, I have a service that requires a constructor parameter not resolved by Autofac, that I instantiate using a delegate factory:
public class Service
{
public Service(string parameter /*, ... other dependencies */)
{
}
public delegate Service Factory(string parameter);
}
This works great! I really love this feature.
I also like the Controlled Lifetime relationship, so I can let my component depend on a Func<Owned<ISomething>> like this:
public class Component
{
private Func<Owned<ISomething>> _somethingFactory;
/* constructor omitted for brevity */
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory())
{
/* Lots of useful code here */
}
}
}
My problem is that now I want to combine the two. I can't have an instance of Func<Owned<Service>> injected, because it needs that parameter, so my current solution is to abstract the factory away into another service, say IServiceFactory:
public interface IServiceFactory
{
Service Create(string parameter);
}
...implemented as such:
public class ServiceFactory : IServiceFactory
{
private Service.Factory _internalFactory;
public ServiceFactory(Service.Factory internalFactory)
{
_internalFactory = internalFactory;
}
public Service Create(string parameter)
{
return _internalFactory(parameter);
}
}
My component then becomes this:
public class Component
{
Func<Owned<IServiceFactory>> _serviceFactoryFactory;
/* ... */
}
The need for such a field name leaves a bad taste in my mouth to the point that I suspect there must be a cleaner way to handle this case.
Is there another way?
You could change your injected factory to include the string parameter:
private Func<string, Owned<ISomething>> _somethingFactory;
Then you can pass the string to the factory when you want to create a new instance:
public void DoSomethingUseful()
{
using (var ownedSomething = _somethingFactory("my parameter"))
{
/* Lots of useful code here */
}
}
I've created a .NET Fiddle with a small working sample.
I have a model object that has a getter/setter that accepts a String.
public String getStringValue(String key)
I need to know if it is possible to use that getter with a PropertyModel and if so how do I do it? An example might look something like this:
new PropertyModel<String>(myObj, "StringValue[key]");
There isn't built in way to do it. But you can define your own Wicket Model to do it via reflection.
For example:
public class FunctionReflectionReadOnlyModel<T, R> extends AbstractReadOnlyModel<T> {
private Object object;
private String functionName;
private R key;
private Class<R> keyClass;
public FunctionReflectionReadOnlyModel(Object object, String expression, Class<R> keyClass) {
this.object = object;
this.functionName = getFunctionName(expression);
this.key = getKey(expression);
this.keyClass = keyClass;
}
#Override
public T getObject() {
try {
Method method = object.getClass().getMethod(functionName, keyClass);
return (T)method.invoke(object, key);
} catch (Exception ex) {
//process exception
return null;
}
}
}
You just need implement getFunctionName(String expression) and getKey(String expression) on your needs.
But I think that is better use another variant. It's not particularly what you ask, but it is typified. Also required Java 8.
public class FunctionWithKeyReadOnlyModel<T, R> extends AbstractReadOnlyModel<T> {
private Function<R, T> function;
private R key;
public FunctionWithKeyReadOnlyModel(Function<R, T> function, R key) {
this.function = function;
this.key = key;
}
#Override
public T getObject() {
return function.apply(key);
}
}
And then you can use it like this:
new FunctionWithKeyReadOnlyModel(obj::getStringValue, "key");
I've read about usage only PropertyModel too late. In this case you can inherit your class from PropertyModel and change getModel/setModel like in example FunctionReflectionReadOnlyModel. So you don't need change other classes API. But if you want all features of PropertyModel (nested objects) you need implement it.
As answered by #merz this is not supported by Wicket's PropertyModel, actually by PropertyResolver.
PropertyResolver supports such access if you use a java.util.Map:
public Map<String, String> getProperty() {return theMap;}
Check org.apache.wicket.core.util.lang.PropertyResolver's javadoc.
Here's the thing.
I have an interface, and I would to put the Include extension method, who belongs to EntityFramework library, to my IRepository layer wich dont needs to knows about EntityFramework.
public interface IRepository<TEntity>
{
IQueryable<TEntity> Entities { get; }
TEntity GetById(long id);
TEntity Insert(TEntity entity);
void Update(TEntity entity);
void Delete(TEntity entity);
void Delete(long id);
}
So I have the extension method:
public static class IncludeExtension
{
static IQueryable<TEntity> Include<TEntity>(this IQueryable<TEntity> query,
string path)
{
throw new NotImplementedException();
}
}
But I don't know how to implement it in this layer, and I would to send it to my EntityFramework (or whatever who will implement the IRepository) to deal with.
I need same to a Interface with a extension method.
Any light?
Include is leaky abstraction and it works only with Entity framework. EF 4.1 already contains Include over generic IQueryable but it internally only converts passed generic IQueryable to generic ObjectQuery or DbQuery and calls their Include.
Here is some example how to wrap that include in repository (repository implementation is dependent on EF so it can use Include provided by EF directly).
This question is a bit old, but here are two EF-independent solutions if you or anyone else is still looking:
1. Reflection-based Solution
This solution is what the .NET Framework falls back to if the IQueryable does not cast to a DbQuery or ObjectQuery. Skip these casts (and the efficiency it provides) and you've decoupled the solution from Entity Framework.
public static class IncludeExtension
{
private static T QueryInclude<T>(T query, string path)
{
MethodInfo includeMethod = query.GetType().GetMethod("Include", new Type[] { typeof(string) });
if ((includeMethod != null) && typeof(T).IsAssignableFrom(includeMethod.ReturnType))
{
return (T)includeMethod.Invoke(query, new object[] { path });
}
return query;
}
public static IQueryable<T> Include<T>(this IQueryable<T> query, string path) where T : class
{
return QueryInclude(query, path);
}
// Add other Include overloads.
}
2. Dyanmics-based Solution
Here the QueryInclude<T> method uses the dynamic type to avoid reflection.
public static class IncludeExtension
{
private static T QueryInclude<T>(T query, string path)
{
dynamic querytWithIncludeMethod = query as dynamic;
try
{
return (T)querytWithIncludeMethod.Include(path);
}
catch (RuntimeBinderException)
{
return query;
}
}
public static IQueryable<T> Include<T>(this IQueryable<T> query, string path) where T : class
{
return QueryInclude(query, path);
}
// Add other Include overloads.
}
In Entity Framework 5.0 they now provide an extension method to IQueryable to add the Include functionality. You will just need to add a using "System.Data.Entity" in order to resolve the extension method. For direct documentation go here
I have an overloaded generic method used to obtain the value of a property of an object of type PageData. The properties collection is implemented as a Dictionary<string, object>. The method is used to avoid the tedium of checking if the property is not null and has a value.
A common pattern is to bind a collection of PageData to a repeater. Then within the repeater each PageData is the Container.DataItem which is of type object.
I wrote the original extension method against PageData:
public static T GetPropertyValue<T>(this PageData page, string propertyName);
But when data binding, you have to cast the Container.DataItem to PageData:
<%# ((PageData)Container.DataItem).GetPropertyValue("SomeProperty") %>
I got a little itch and wondered if I couldn't overload the method to extend object, place this method in a separate namespace (so as not to pollute everything that inherits object) and only use this namespace in my aspx/ascx files where I know I've databound a collection of PageData. With this, I can then avoid the messy cast in my aspx/ascx e.g.
// The new overload
public static T GetPropertyValue<T>(this object page, string propertyName);
// and the new usage
<%# Container.DataItem.GetPropertyValue("SomeProperty") %>
Inside the object version of GetPropertyValue, I cast the page parameter to PageData
public static T GetPropertyValue<T>(this object page, string propertyName)
{
PageData data = page as PageData;
if (data != null)
{
return data.GetPropertyValue<T>(propertyName);
}
else
{
return default(T);
}
}
and then forward the call onto, what I would expect to be PageData version of GetPropertyValue, however, I'm getting a StackOverflowException as it's just re-calling the object version.
How can I get the compiler to realise that the PageData overload is a better match than the object overload?
The extension method syntax is just syntactic sugar to call static methods on objects. Just call it like you would any other regular static method (casting arguments if necessary).
i.e.,
public static T GetPropertyValue<T>(this object page, string propertyName)
{
PageData data = page as PageData;
if (data != null)
{
//will call the GetPropertyValue<T>(PageData,string) overload
return GetPropertyValue<T>(data, propertyName);
}
else
{
return default(T);
}
}
[edit]
In light of your comment, I wrote a test program to see this behavior. It looks like it does go with the most local method.
using System;
using Test.Nested;
namespace Test
{
namespace Nested
{
public static class Helper
{
public static void Method(this int num)
{
Console.WriteLine("Called method : Test.Nested.Helper.Method(int)");
}
}
}
static class Helper
{
public static void Method(this object obj)
{
Console.WriteLine("Called method : Test.Helper.Method(object)");
}
}
class Program
{
static void Main(string[] args)
{
int x = 0;
x.Method(); //calls the object overload
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
Console.WriteLine();
}
}
}
To make sure the nesting is not affecting anything, tried this also removing the object overload:
using System;
using Test.Nested;
namespace Test
{
namespace Nested
{
public static class Helper
{
public static void Method(this int num)
{
Console.WriteLine("Called method : Test.Nested.Helper.Method(int)");
}
}
}
static class Helper
{
public static void Method(this string str)
{
Console.WriteLine("Called method : Test.Helper.Method(string)");
}
}
class Program
{
static void Main(string[] args)
{
int x = 0;
x.Method(); //calls the int overload
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
Console.WriteLine();
}
}
}
Sure enough, the int overload is called.
So I think it's just that, when using the extension method syntax, the compiler looks within the current namespace first for appropriate methods (the "most local"), then other visible namespaces.
It should already be working fine. I've included a short but complete example below. I suggest you double-check your method signatures and calls, and if you're still having problems, try to come up with a similar short-but-complete program to edit into your question. I suspect you'll find the answer while coming up with the program, but at least if you don't, we should be able to reproduce it and fix it.
using System;
static class Extensions
{
public static void Foo<T>(this string x)
{
Console.WriteLine("Foo<{0}>(string)", typeof(T).Name);
}
public static void Foo<T>(this object x)
{
Console.WriteLine("Foo<{0}>(object)", typeof(T).Name);
string y = (string) x;
y.Foo<T>();
}
}
class Test
{
static void Main()
{
object s = "test";
s.Foo<int>();
}
}