Lucene 'join' how-to? - lucene.net

Using Nhibernate.Search at the moment.
Some code for context:
[Indexed]
class foo {
[DocumentId]
int id {get;set;}
bar bar {get;set;}
}
[Indexed]
class bar {
[DocumentId]
int id {get;set;}
}
Question:
How to retrieve all foos where foo.bar.id==1 using IFullTextQuery?

If you want to include related information into the foo index you may look into the IndexedEmbeddedAttribute. This will allow you to query for relationships such as if there was a Name property on the bar object you could create a query such as this
IFullTextQuery query = search.CreateFullTextQuery("bar.Name:Arnis");
query.List<foo>();

Seems that [IndexedAttribute] is an answer.

Related

Entity Framework navigation with only foreign key

Following the guide lines from Domain Driven Design, I try to avoid having one aggregate referencing a different aggregate. Instead, an aggregate should reference another aggregate using the other aggregate's id, for example:
public class Addiction
{
private Addiction(){} //Needed for EF to populate non-simple types
//DrugType belongs to the aggregate,
//inflate when retrieving the Addiction from the db
//EF does not need DrugId for navigation
Drug Drug{get;set;}
//The supplier is not part of the aggregate,
//aggregates only reference eachother using Ids
int SupplierId{get;set;}
//Other properties
}
public class AddictionConfiguration : IEntityTypeConfiguration<Addiction>
{
builder.HasOne(addiction => addiction.Drug); //Works
builder.HasOne("SupplierId") //Does not work.
}
In this (not very realistic) example, Drug is part of the Addiction's aggregate. When loading this entity from the database using EF, it will also inflate the Drug property without me having to specify the DrugId as the foreign key.
However, now I need to get a list of all Addictions and their suppliers by mapping the relevant properties to a Dto. I try to achieve this by using AutoMapper's ProjectTo functionality, e.g.
_mapper.ProjectTo<AddictionDto>(_dbContext.Addictions.Where(x => x.Id > 1));
where AddictionDto is defined as
public class AddictionDto
{
DrugDto Drug {get;set;}
SupplierDto Supplier {get;set;}
//other properties
}
And
public class SupplierDto
{
public int Id {get;set;}
public string Name {get;set;}
}
Automapper correctly loads the Addiction and also the Drug, but I cannot get it to load the Supplier. I've tried all the options of the IEntityTypeConfiguration to tell EF that there is a navigation property, but I cannot get it to work. Does anyone know if is even possible to do what I described above?

Including read-only columns in an Entity Framework model

Suppose I have a .NET Entity Framework model class:
public class Foo
{
public int FooId { get; set; }
public string Description { get; set; }
public DateTime Created { get; set; }
public DateTime LastUpdated { get; set; }
}
The Created and LastUpdated columns in my SQL Server table, both of type DATETIME2, have a DEFAULT constraint (SYSUTCDATETIME()). An AFTER UPDATE trigger sets LastUpdated to SYSUTCDATETIME whenever the Description is changed.
In my code, when I'm reading from the Foo table, I want Created and LastUpdated included, because I want to use their values. But when I'm adding a row to the table, I don't want them included in the Add because I want SQL Server to use the default value I've configured it to use. I thought it would just have been a matter of having
Foo foo = new Foo
{
Description = "This is my latest foo."
}
but C# is giving the two date properties their own default value of 0001-01-01T00:00:00.000000, which isn't null, and this is what's getting recorded in the table.
Isn't there an attribute that tells the framework not to write a property back to the database? It isn't NotMapped because that would prevent the values from being read.
`Don't you hate when you find the answer right after posting your question?
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] omits the property from inserts and updates.
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] omits the property from inserts.
The latter will take care of EndDate, which I didn't illustrate in my post. I have the database set a default value of 9999-12-31T23:59:59 on insert, but my application will change its value later when Foo is meant to expire.
What kills me is they based the naming on specific use cases that wouldn't come to mind in a different scenario. They ought to have gone with [SkipOnInsert] and [SkipOnUpdate] (which could then be combined as needed).

Entity Framework equivalent of NHibernate "subselect fetching"

NHibernate has a fetching strategy called "Subselect Fetching" which is detailed here: https://nhibernate.info/doc/nhibernate-reference/performance.html
TLDR: the idea is when we have an entity like this:
class Foo
{
ICollection<Bar> Bars { get; set; }
}
rather than doing a join, we can retrieve both the Foos and the Bars in separate queries (with the results stitched together by NHibernate). In pseudo code:
SELECT * FROM Foo WHERE Name = 'John'
SELECT * FROM Bar WHERE FooId IN (:idFromFirstQuery)
This is useful in the case that Foo is wide and joining to Bar would retrieve a large amount of data.
Is there an equivalent in Entity Framework?
Answering my own question, this can be achieved like this:
var foos = DbContext.Set<Foo>().Where(x => x.Name == 'John').ToList();
var fooIds = foos.Select(x => x.Id).ToArray();
var bars = DbContext.Set<Bar>().Where(x => foos.Contains(x.FooId)).ToList();
The bars variable is then just thrown away (and Resharper will get annoyed), however by virtue of this all occurring within the same DbContext, the Foos will now have their Bar collections populated.

How to search on contents of a referenced field in morphia

Lets say that I have classes like this:
public class Foo{
#id
ObjectID id;
#Reference
Bar bar;
long fooValue;
}
public class Bar {
#id
ObjectID id;
#Reference
Baz baz;
long barValue;
}
public class baz{
#id
ObjectID
String content;
}
If I want to load all foo objects in which the referenced baz has a certain value what syntax should I use? Lets see I want all foo in which the referenced baz.content value is "foobar" how can I do it? Would it be quicker to work backwards by looking up all baz and then finding all bar that reference it etc?
This won't work (well) with MongoDB. What you are trying to do is a JOIN, which doesn't exist.
What you can do is:
Query Baz, which gets you a Baz.ObjectId (for each match).
Query the Bar that references the Baz.ObjectId, which gets you a Bar.ObjectId
Do the same for Foo referencing the Bar.ObjectId
So for each matched document in Baz you'll need two more queries to get its Foo.
Could you embed Baz into Bar and Bar into Foo? Then you'd only need a single query.

Access underlying DbContext (or run stored procedure) from Entity Framework POCO method

Is it possible to access the underlying DbContext (the DbContext that has populated this object/has this object in its cache/is tracking this object) from inside a model object, and if so, how?
The best answer I have found so far is this blog post which is five years old. Is it still the best solution available?
I’m using the latest version of Entity Framework if that matters.
Here's a sample to clarify my question:
I have a hierarchical tree. Let’s say it is categories that could have sub-categories. The model object would be something like this:
class Category
{
string CategoryId { get; set; }
string Name { get; set; }
virtual Category Parent { get; set; }
virtual ICollection<Category> Children { get; set; }
}
Now, if I want to access all descendants of a category (not just its immediate children) I can use a recursive query like this:
class Category
{
//...
IEnumerable<Category> Descendants
{
get
{
return Children.Union(Children.SelectMany(q => q.Descendants));
}
}
}
which works, but has bad performance (due to multiple database queries it needs to perform).
But suppose I have an optimized query that I can run to find descendent (maybe I store my primary key in a way that already contains path, or maybe I’m using SQL Server data type hierarchyid, etc.). How can I run such a query, which needs access to the whole table/database and not just the records available through model object’s navigational properties?
This can be either done by running a stored procedure/SQL command on the database, or a query like this:
class Category
{
//...
IEnumerable<Category> Descendants
{
get
{
// this won't work, because underlying DbContext is not available in this context!
return myDbContext.Categories.Where(q => q.CategoryId.StartsWith(this.CategoryId));
}
}
}
Is there a way at all to implement such a method?