2

can anyone give some reference for non-sql database query interface design pattern?

For sql-based database, the query can be achieved by combining the query token. but for non-sql, how to design the query, given that the query could be very complex.

EDIT:

I am using db4o to store some objects, I may need to query according to a certain Id, time range, or the combination of them.

How to design the query method?

public IEnumerable<Foo> GetFoos(int id);
public IEnumerable<Foo> GetFoos(int id, TimeRange range);

To build a lot of overloads seem stupid, what if a new query is needed?

Álvaro González
  • 142,137
  • 41
  • 261
  • 360
Benny
  • 8,547
  • 9
  • 60
  • 93
  • 1
    The word "query" is used very loosely in your question. Please be more specific in what type of query and what "non-sql database" you're referring to. – Benny May 04 '10 at 03:13
  • @Benny, Hi, Benny, I am Benny too. :) – Benny May 04 '10 at 03:37
  • Hm, are you considering the use of the Repository pattern here? Is that what you mean by 'query' and 'overload'? – mnemosyn May 04 '10 at 08:37

2 Answers2

3

In C#, it's definitely best to use Linq. Native Queries often fail to optimize, which will lead db4o to hydrate all objects and actually call the lambda expression on the instantiated object. That is nothing but an automated fallback to linq-to-objects and it's damn slow in comparison. Merely hydrating 60k of our typical objects takes multiple seconds.

Hint: A breakpoint on the lambda expression must never be invoked.

Even when using Db4oTool.exe to optimize native queries as a post-build step, even simple queries lead to problems when using properties or auto-properties in domain objects.

The linq provider always gave the best results for me. It has the most concise syntax and it's optimizations work. Also the linq provider is very complete, only it might fall back to linq-to-objects more often than you expect.

Also, it's important for the linq provider to have certain dlls in the project folder. Which these are depends on the version a bit. If you are using builds >= 14204, make sure Mono.Reflection.dll is in your app folder.

For older versions, all of the following must be present:

Db4obects.Db4o.Instrumentation.dll
Db4objects.Db4o.NativeQueries.dll
Mono.Cecil.dll
Cecil.FlowAnalysis.dll

Note that for native queries these are still required even in newer builds.

mnemosyn
  • 45,391
  • 6
  • 76
  • 82
  • 1
    Hi. I am a member of db4o core team. I am curious, which problems are you facing when using Native Queries with simple properties? If the property is really a simple "getter" you should have no problems. Anyway, IMHO, LINQ is the best option for queries in .Net 3.5. Regarding LINQ, starting with build 14204 db4o LINQ provider (for the desktop framework) depends only on Mono.Reflection.dll (and on Db4objects.Db4o.dll :)) – Vagaus May 04 '10 at 11:23
  • Hey Adriano, thanks for your comment and agreeing that LINQ is the best option for .NET 3.5 =) I think German forwarded one my issues related to `DateTime` to you. As for the query optimization: Query optimization fails even for simple cases (auto properties). The query is orders of magnitudes slower than with linq. Linq apparently uses the BTree (roughly log n) while NQ is linear at best. Tried both using in-place NQ and `Db4oTool` IL weaving. – mnemosyn May 04 '10 at 13:24
1

It looks like db4o uses its own queries, which Versant calls Native Queries (note: there's a separate syntax for .Net and Java native queries). Something like:

IObjectContainer container = Database();
container.Query(delegate(Foo foo) {
    return foo.id == id;
});

container.Query(delegate(Foo foo) {
        return foo.id == id;
    },
    delegate(Foo foo) {
        return range.IsIn(foo.time);
    });
outis
  • 75,655
  • 22
  • 151
  • 221
  • so, basically, i should define the query method like this: GetFoos(Predict predicator), right? – Benny May 04 '10 at 04:08
  • Or `GetFoos` could take a `bool delegate(Foo)`, which `Database.Query` also supports. – outis May 04 '10 at 04:46
  • In which version does the `Query()` method accept a second delegate? What is the second delegate supposed to do? Why explicitly declare the delegate instead of using lambda methods? Why not use linq? `range.IsIn()` can definitely not be optimized so it shouldn't be used in a query under any circumstances. – mnemosyn May 04 '10 at 08:12
  • 1
    @mnemosyn: all good points. `Query()` taking two delegates comes straight from the documentation, as did using explicit delegates. Since OP didn't specify which version of .Net he was targetting, I was sticking to 2.0. Does db4o support LINQ under .Net 2? The docs (http://www.db4o.com/s/linqdb.aspx) only mention 3.5. – outis May 04 '10 at 09:53
  • @outis: No. Since LINQ support was introduced in the platform in .Net 3.5 and newer db4o can't support it in older versions (I am aware that it may be possible to get it working with hacks but IMHO it don't worth the trouble). – Vagaus May 04 '10 at 11:31
  • @outis: Granted, I shouldn't assume that everybody is using the latest (applicable) version, and in .NET 2.0 I'd also stick to NQ, *if* I could find the reasons for my optimization issues. The `Query` with two delegates still puzzles me and has a very inconvenient interface. db4o's documentation is tricky because there are so many coexisting versions and some documentation inconsistencies, so I wouldn't rely on that. – mnemosyn May 04 '10 at 13:26