Separate out two identical collections except for different ids with LINQ - c#

I am trying to produce a method which feeds in two database (.db) files, loads them into an object which contains various string properties and a unique ID.
The db files were created from a LiteDB instance, with a unique ID assigned under the LiteDB library method, like so:
Id = ObjectID.NewObjectId();
I'm trying to obtain all items that are different between the two db collections, but unfortunately any LINQ query I try falls down because the IDs are always unique, despite all other values contained within the object being identical.
I would like to perform a LINQ query that will ignore the ID field in the object but do a comparison on all other properties within that object but am struggling to do so
My initial idea was to use
var differences = items1.Except(items2)
But this populates all items into the differences collection, due to the differing IDs.
Any advice on how to exclude the comparison of the ids would be appreciated, the tool may be used on millions of records so needs to be efficient.

Except has an overload that accepts an IEqualityComparer<T>. You can implement this interface in a class in a way that ignores the ID and then pass an instance of that class to the method. See this example if you need a reference on how to implement IEqualityComparer<T>.

Related

EntityFrameworkCore reading data using reflection - how to create DbSet when type unknown

I am working with a .Net 6 Console application where I need to read data from tables in a custom DbContext using Microsoft.EntityFrameworkCore
I have added the entities to the model in OnModelCreating() and can get them back using a call to
var entity = ctx.Model.GetEntityTypes().FirstOrDefault(e => e.FullName().InfexOf(tableName) >= 0);
Given that, how to I retrieve a list of data, for example entity.ToList() - the type returned for entity is IEntityType?.
As an alternate (and my preferred way if possible), I have created an array of tables using reflection (they all inherit from BaseTable), they are stored as a list.
I would like to create a DbSet<> using DbContext.Set() so that I can use Find(), AsNoTracking() and other such commands (including write operations).
I have the following:-
IQueryable<Object>dbSet = (IQueryable<Object>)ctx
.GetType()
.GetMethod("Set",1,Type.EmptyTypes)
.MakeGenericMethod(t)
.Invoke(ctx, null);
Which allows me to do something like dbSet.ToList(), but I would really like to cast it to a DbSet.
Does anyone know if it is possible to make such a conversion?
(I am reading only a few records from sets of tables and then writing data back to a different database (with the same tables).
Update: *Another way of thinking about this: I am iterating across a collection of tables. I need to pull out the PK and two other columns (for which I have the name of at runtime) - if the value of column 1 contains a specific value, I need to update the value of column 2 *
You can't really do that. However, you can cast the database value to specific types based on discriminators. Take a look at this https://learn.microsoft.com/en-us/ef/core/modeling/value-conversions?tabs=data-annotations

Generic joined column ordering in NHibernate

I'm using fluent NHibernate in a large project. There's a lot of generic code written, including column ordering.
Suppose I have an QueryOver object, with fetch-joins already inside, and a list of objects describing which columns I'd like to order by and in what order, for instance on the joined column "Owner.Name" of the class contained in the QueryOver. How would I go about adding this order criteria to the QueryOver?
I solved this by using the method -queryOverObject-.RootCriteria.CreateAlias(associationPath, alias).
For example, to sort by the joined property Owner.Nameof an object, I just call CreateAlias("Owner", "Owner"), and can then do .RootCriteria.AddOrder(Order.Desc("Owner.Name")).

The optimal way to load referenced entities from other collections from C# and MongoDb

In my Mongo database I have two collections, let's they are A and B.
Entities of type A has, for example, a list of ids of entities of type B. This list is just a list of strings, where each string is a string representation of B's Id.
I want to reflect these reference relationships in my domain classes (and data classes at the same time) more clearly, so that I have a list of Bs inside of A, and would be able to query this list with possible filtering or ordering via LINQ.
Currently this is implemented in the following way:
I have a class MongoReference with a static event named 'MongoReferenceLoadRequested'. This event has event args that contain a type of referenced item and its id, also it has a read-write property of type Object, where the actual loaded object is supposed to be written to.
The event is fired whenever somebody wants to have an access to A's instance's list of Bs.
In my Global.asax.cs I subscribe to this event and in the handler load desired entity and assign it to event args' property. This is done to decouple application configuration, where MongoDb connection string is stored, and POCO entities classes, that do not have (and should not have) access to connection string.
How do you think, is this a correct way of achieving my goals?
Consider revisiting your document model in MongoDB. Sounds like a good candidate for having A have an array of B inside it in MongoDB.
// Document A:
{
_id: ... ,
values: [B1,B2,B3 ..]
}
This Impedance Mismatch is a legacy of RDBMS, and is due to implied relationships and the table-row kind of modeling and thinking.
See here for examples and discussion of appropriate data modeling in some common scenarios.

Using Unmapped Class with NHibernate Named Query

I'm using a custom named query with NHibernate which I want to return a collection of Person objects. The Person object is not mapped with an NHibernate mapping which means I'm getting the following exception:
System.Collections.Generic.KeyNotFoundException:
The given key was not present in the
dictionary.
It's getting thrown when the Session gets created because it can't find the class name when it calls NHibernate.Cfg.Mappings.GetClass(String className). This is all fairly understandable but I was wondering if there was any way to tell NHibernate to use the class even though I haven't got a mapping for it?
Why don't you use:
query.SetResultTransformer(Transformers.AliasToBean(typeof(Person)));
It will insert data from each column in your query into Person object properties using column alias as a property name.
How can you create a query which would return instances of a type that is not mapped ?
I think Michal has a point here, and maybe you should have a look at projections. (At least, this is what I think you're looking for).
You create a query on some mapped type, and then, you can 'project' that query to a 'DTO'.
In order to do this, you'll have to 'import' your Person class, so that it is known to NHibernate, and you'll have to use a ResultTransformer.
Something like this:
ICriteria crit = session.CreateCriteria (typeof(Person));
// set some filter criteria
crit.SetProjection (Projections.ProjectionList()
.Add (Property("Name"), "Name")
.Add (Property( ... )
);
crit.SetResultTransformer(Transformers.AliasToBean(typeof(PersonView));
return crit.List<PersonView>();
But, this still means you'll have to import the class, so that NHibernate knows about it.
By using the class, NHibernate would basically be guessing about everything involved including which table you meant to use for Person, and the field mappings. NHibernate could probably be hacked to do dynamic binding based on matching the names or something, but the whole idea is to create the mappings from plain old data object to the database fields using the xml files.
If there's not a really good reason not to map the class, simply adding the mapping will give you the best results...
That said, you can't use a named query to directly inject results into an unmapped class. You would need to tell it which columns to put into which fields or in other words, a mapping. ;) However, you can return scalar values from a named query and you could take those object arrays and build your collection manually.
To solve this, I ended up using the TupleToPropertyResultTransformer and providing the list of property values. There are a few limitations to this, the main one being that the SQL query must return the results in the same order as you provide your properties to the TupleToPropertyResultTransformer constructor.
Also the property types are inferred so you need to be careful with decimal columns returning only integer values etc. Apart from that using the TupleToPropertyResultTransformer provided a reasonably easy way to use an SQL query to return a collection of objects without explicitly mapping the objects within NHibernate.

NHibernate - Getting the results as an IDictionary instead of IList

I'm using NHibernate as a persistency layer and I have many places in my code where I need to retrieve all the columns of a specific table (to show in a grid for example) but i also need a fast way to get specific item from this collection.
The ICriteria API let me get the query result either as a unique value of T or a IList of T.
I wonder if there is a way to make NHibernate give me those objects as an IDictionary where the key in the object's Id and the value is the object itself. doing it myself will make me iterate all over the original list which is not very scalable.
Thank you.
If you are working with .NET 3.5, You could use the Enumerable() method from IQuery, then use the IEnumerable<T>.ToDictionary() extension method :
var dictionary = query.Enumerable().ToDictionary(r => r.Id);
This way, the list would not be iterated twice over.
You mention using ICriteria, but it does not provide a way to lazily enumerate over items, whereas IQuery does.
However, if the number of items return by your query is too big, you might want to consider querying the database with the key you'd have used against the IDictionary instance.

Categories

Resources