I have:
public class Movie : IMongoEntity
{
public ObjectId Id { get; set; }
public string Title { get; set; }
public string Year { get; set; }
public List<Actor> Actors { get; set; }
}
public class Actor : IMongoEntity
{
public ObjectId Id { get; set; }
public string Name { get; set; }
}
If i want to retrieve the entire movie collection I do
var query = this.MongoConnectionHandler.MongoCollection.FindAllAs<Movie>();
No I want to retrieve just the movies that have an actor with a certain name
I've tried something like:
IMongoQuery query = Query<Movie>.Where(m => m.Actors.Select(a => a.Name).Any(n => n.Contains(actorName)));
var exc = this.MongoConnectionHandler.MongoCollection.Find(query);
But that won't work.
I think this should do the trick:
var query = Query<Movie>.ElemMatch(m => m.Actors, builder => builder.EQ(actor => actor.Name, actorName));
var exc = this.MongoConnectionHandler.MongoCollection.Find(query);
Related
Parent table
public class Activity
{
public int ActivityId { get; set; }
public string ActivtiyName { get; set; }
[JsonIgnore]
public List<ActivityFeature> ActivityFeature { get; set; }
}
child table
public partial class ActivityFeature
{
public int FeatureId { get; set; }
public string FeatureName { get; set; }
public bool IsChecked { get; set; }
//Navigation properties
public int ActivityId { get; set; }
public Activity Activity { get; set; }
}
controller
public async Task<ActionResult<IEnumerable>> GetActivity()
{
//_context.Activity.Include(e => e.ActivityFeature).ToList();
var Activty = _context.Activity
.Select(c => new
{
ActivityId = c.ActivityId,
ActivityFeatures = c.ActivityFeature
}).ToList();
return _context.Activity;
}
Try this
var activty = _context.Activity
.Include(i=> i.ActivityFeature)
.ToList();
or if you want for one activity witn id
var activty = _context.Activity
. Where (i=> i.ActivityId==id)
.Include(i=> i.ActivityFeature)
.FirstOrDefault();
or just child table
var activtyFeatures = _context.Activity
. Where (i=> i.ActivityId==id)
.Select(i=> i.i.ActivityFeature)
.FirstOrDefault();
or the same result
var activtyFeatures = _context.ActivityFeature
.Where(i=> i.ActivityId=id)
.ToList();
I want to reduce duplicated code. In order to achieve that I want to reference the projections of my Entities.
Entities
public class Category
{
public string Id { get; set; }
public string CategoryName { get; set; }
public static Expression<Func<Category, Category>> Proj() => c => new Category
{
CategoryName = c.CategoryName
};
}
public class Image
{
public string Id { get; set; }
public string Url { get; set; }
public static Expression<Func<Image, Image>> Proj() => i => new Image
{
Url = i.Url
};
}
public class Product
{
public string Id { get; set; }
public string Name { get; set; }
public ICollection<Image> Images { get; set; }
public Category Category { get; set; }
}
Projection Query
var categoryProjection = Category.Proj().Compile();
var products = _ctx.Products.Select(p => new Product
{
Id = p.Id,
Name = p.Name,
Images = p.Images.AsQueryable().Select(Image.Proj()).ToHashSet(),
Category = categoryProjection.Invoke(p.Category)
});
When I execute the projection then it will work correctly for Product and Images. But for Category the genereted SQL will contain all Columns (Id and CategoryName).
I have a stored proc returning a datatable using a stored procedure. I am able to convert the it to an object using the following code
outgoingPaymentData.AsEnumerable().Select(x => new OutgoingPaymentApprovalDetails() { });
Here is my OutgoingPaymentApprovalDetails class
public class OutgoingPaymentApprovalDetails
{
public int OriginatorId { get; set; }
public string Name { get; set; }
public string DocumentId { get; set; }
public string DebtorName { get; set; }
public string Currency { get; set; }
public double Amount { get; set; }
public string Description { get; set; }
public string DebitAccountNo { get; set; }
public string CreditAccountNo { get; set; }
}
Now, instead of a flat list, I need to add heirarchy, to select this one object to 3 objects.
Classes as under:
public class OriginatorDetails
{
public int OriginatorId { get; set; }
public string Name { get; set; }
public List<DocumentDetails> DocumentDetails { get; set; }
}
public class DocumentDetails
{
public string DocumentId { get; set; }
public List<TransactionDetails> TransactionDetails { get; set; }
}
public class TransactionDetails
{
public string Amount { get; set; }
public string DebitAccountNo { get; set; }
public string CreditAccountNo { get; set; }
}
Basically, All Documents of a particular Originator have to be in the list of DocumentDetails and all TransactionDetails of a particular document have to be in that list.
One way is to create a dictionary and add stuff in it and finally create an object. I was wondering if there was a more abbreviated and efficient way to do something like this.
TIA
You can do the grouping of retrieved records of OutgoingPaymentApprovalDetails using Linq to create the nested object of OriginatorDetails collection.
see below code
var originalDetails = inputs.GroupBy(g => g.OriginatorId)
.Select(g => new OriginatorDetails()
{
OriginatorId = g.Key,
Name = g.First().Name,
DocumentDetails = g.GroupBy(d => d.DocumentId)
.Select(d => new DocumentDetails()
{
DocumentId = d.Key,
TransactionDetails = d.Select(t => new TransactionDetails()
{
DebitAccountNo = t.DebitAccountNo,
CreditAccountNo = t.CreditAccountNo,
Amount = t.Amount.ToString()
}).ToList()
})
.ToList()
});
Check the created https://dotnetfiddle.net/FCA7Qc to demostrate your scenario.
Try this code:
Basically you need to group 2 times, first time by OriginatorId and Name and then by DocumentId like this:
var result = list.GroupBy(c => new {c.OriginatorId, c.Name})
.Select(g => new OriginatorDetails()
{
Name = g.Key.Name,
OriginatorId = g.Key.OriginatorId,
DocumentDetails = g
.GroupBy(dd => dd.DocumentId)
.Select(dd => new DocumentDetails()
{
DocumentId = dd.Key,
TransactionDetails = dd.ToList()
.Select(td => new TransactionDetails()
{
Amount = td.Amount.ToString(),
CreditAccountNo = td.CreditAccountNo,
DebitAccountNo = td.DebitAccountNo
}).ToList()
}).ToList()
}).ToList();
I have a 'User' class with a list of organisations. With [BsonIgnore] I'm not saving the organisations. They are in another collection. That's why 'User' also has a list of organisationId's. This works fine.
public class User
{
public ObjectId _id { get; set; }
public List<ObjectId> OrganisationIds { get; set; }
[BsonIgnore]
public List<Organisation> Organisations { set; get; }
}
Problem
The problem is when I do a query to get the User and his organisations. On deserializing the BsonDocument, It throws an exception. Something like: 'Organisations' on 'User' does not exists.
var aggregation = _userService.GetCollection()
.Aggregate<User>()
.Lookup<User>("Organisations", "OrganisationId", "_id", "Organisation");
var firstUser = aggregation.FirstOrDefault();
var user = BsonSerializer.Deserialize<User>(firstUser);
I don't want to save organisations in a user. How should I approach this?
The [BsonIgnore] caused the trouble. It didn't complain about there is no such field, but it complained when aggregating.
I have the following, and it's working>
public class User
{
public ObjectId _id { get; set; }
public List<ObjectId> OrganisationIds { get; set; }
}
public class UserAggregate
{
public List<ObjectId> OrganisationIds { get; set; }
public ObjectId _id { get; set; }
public List<Organisation> Organisations { set; get; }
}
public class Organisation
{
public ObjectId _id { get; set; }
public string Name { get; set; }
}
string connectionString = "mongodb://localhost:27017";
var client = new MongoClient(connectionString);
var db = client.GetDatabase("test");
var instances = db.GetCollection<User>("Users");
var instances2 = db.GetCollection<Organisation>("Organisations");
var aggregation = instances.Aggregate().Match(...).Lookup(foreignCollection: instances2,
localField: x => x.OrganisationIds, foreignField: x => x._id,
#as: (UserAggregate pr) => pr.Organisations)
.ToList();
I am using Entity Framework 5 and I have these classes. What I want to do is to be able to get the data to populate the view listed below:
public partial class Subject
{
public int SubjectId { get; set; }
public string Name { get; set; }
public virtual ICollection<Topic> Topics { get; set; }
}
public partial class Topic
{
public int TopicId { get; set; }
public string Name { get; set; }
public int SubjectId { get; set; }
public virtual Subject Subject { get; set; }
public virtual ICollection<SubTopic> SubTopics { get; set; }
}
public partial class SubTopic
{
public int SubTopicId { get; set; }
public string Name { get; set; }
public int TopicId { get; set; }
public virtual Topic Topic { get; set; }
}
Now I am trying to write a LINQ query to populate this class:
public class TopicSubTopicSelect
{
public int TopicId { get; set; }
public int SubTopicId { get; set; }
public string TopicName { get; set; }
public string SubTopicName { get; set; }
}
So far I have this:
return _subjectsRepository
.GetAll()
.Where(s => s.SubjectId == subjectId)
.Include(s => s.Topics.SelectMany(t => t.SubTopics))
.AsEnumerable()
.Select(item => new TopicSubTopicSelect(item.TopicId <<<
item.SubTopicId <<
item.Topic.Name <<
item.Name <<))
.ToList();
Can someone tell me how I can get data from the fields I marked with <<. I tried to do .item.Topic.TopicId etc but that does not seem to work.
You shouldn't start from Subject. You just start from SubTopic Repository, and you won't even need to use .Include. Do it like this:
_subTopicRepository
.GetAll()
.Where(s => s.Topic.SubjectId == subjectId)
.Select(s => new TopicSubTopicSelect()
{
TopicId = s.TopidId,
SubTopicId = s.SubTopicId,
TopicName = s.Topic.Name,
SubTopicName = s.Name
})
.ToList();
As I mentioned in my comment on ataravati's answer, you shouldn't actually have a SubTopicRepository so you are correct in starting at SubjectsRepository however you are querying by the Subject ID so you shouldn't be going via GetAll(), you should have a Get(int id) method. The include should be handled as an implementation detail inside Get as the children (SubTopics) are part of the Subject. That makes the method call look like this instead:
return _subjectsRepository
.Get(subjectId)
.SelectMany(subject => subject.SubTopics))
.Select(subTopic => new TopicSubTopicSelect
{
TopicId = subTopic.TopicId,
SubTopicId = subTopic.SubTopicId,
TopicName = subTopic.Topic.Name,
SubTopicName = subTopic.Name
}).ToList();