My test is setup with mocking data like this
var persons = new List<Core.Domain.Person>
{
new Core.Domain.Person { DisplayName = "Coordinator 1", Email="coordinator01#wur.nl", WurAccount = "coord001" },
new Core.Domain.Person { DisplayName = "Coordinator 2", Email="coordinator02#wur.nl", WurAccount = "coord002" }
};
this.mockUnitOfWork.Setup(x => x.Query<Core.Domain.Person>()).Returns(persons.AsQueryable);
In the code to test the persons are retrieved like this
private Dictionary<string, Domain.Person> GetPersons(IEnumerable<string> wurAccounts)
{
var accounts = wurAccounts.ToList();
return this.session.Query<Domain.Person>()
.Where(x => accounts.Contains(x.WurAccount))
.ToDictionary(x => x.WurAccount);
}
When I run the test I get a NullReferenceException here:
at NHibernate.Linq.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
at Remotion.Linq.QueryableBase`1.GetEnumerator()
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at System.Linq.Enumerable.ToDictionary[TSource,TKey](IEnumerable`1 source, Func`2 keySelector)
at Wur.P2G.Core.Services.PersonSynchronizer.GetPersons(IEnumerable`1 wurAccounts) in C:\Projects\P2G\P2G\Sources\Wur.P2G.Core\Services\PersonSynchronizer.cs:line 112
EDIT
I was able to boile it down to this piece of code that still causes the NullReference Exception:
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using NHibernate;
using NHibernate.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Wur.P2G.Core.Services.Tests
{
public interface IUnitOfWork : IDisposable
{
ISession Session { get; }
IQueryable<T> Query<T>();
void BeginTransaction();
void Commit();
void Rollback();
}
public class Person
{
public virtual string WurAccount { get; set; }
public virtual string DisplayName { get; set; }
public virtual string Email { get; set; }
public virtual bool HasValidEmail => true;
public override string ToString() => WurAccount;
}
[TestClass()]
public class PersonSynchronizerTests
{
private Mock<IUnitOfWork> mockUnitOfWork;
private Mock<ISession> mockSession;
[TestInitialize]
public void Initialize()
{
this.mockUnitOfWork = new Mock<IUnitOfWork>();
this.mockSession = new Mock<ISession>();
this.mockUnitOfWork.Setup(x => x.Session).Returns(this.mockSession.Object);
}
[TestMethod()]
public void GetPersonsTest()
{
var persons = new List<Person>
{
new Person { DisplayName = "Coordinator 1", Email="coordinator01#wur.nl", WurAccount = "coord001" },
new Person { DisplayName = "Coordinator 2", Email="coordinator02#wur.nl", WurAccount = "coord002" }
};
this.mockUnitOfWork.Setup(x => x.Query<Person>()).Returns(persons.AsQueryable);
var wurAccounts = new[] { "coord001", "coord002" };
var accounts = wurAccounts.ToList();
var personsRead = mockSession.Object.Query<Person>()
.Where(x => accounts.Contains(x.WurAccount))
.ToDictionary(x => x.WurAccount);
}
}
}
Some more text because the stupid editor want it from me.
While the error message shows that the problem is related to NHibernate.Linq, None of the code shown so far is related to NHibernate unless there is something you are not showing that is using it.
The code shown so far should work as expected as demonstrated by the following minimal, complete and verifiable example based on the original example provided.
[TestClass]
public class PersonSynchronizerTest {
[TestMethod]
public void PersonSynchronizer_GetPerson_Should_Return_Two() {
//Arrange
var wurAccounts = new[] { "coord001", "coord002" };
var persons = new List<Person> {
new Person { DisplayName = "Coordinator 1", Email="coordinator01#wur.nl", WurAccount = wurAccounts[0] },
new Person { DisplayName = "Coordinator 2", Email="coordinator02#wur.nl", WurAccount = wurAccounts[1] }
};
var mockSession = new Mock<ISession>();
mockSession.Setup(_ => _.Query<Person>()).Returns(persons.AsQueryable); //<-- setup session
var mockUnitOfWork = new Mock<IUnitOfWork>();
mockUnitOfWork.Setup(_ => _.Query<Person>()).Returns(persons.AsQueryable);
mockUnitOfWork.Setup(_ => _.Session).Returns(mockSession.Object); //<-- UoW returns session
var subject = new PersonSynchronizer(mockUnitOfWork.Object);
//Act
var actual = subject.GetPersons(wurAccounts);
//Assert
actual.Should()
.NotBeNull()
.And.HaveCount(wurAccounts.Length);
}
public class PersonSynchronizer {
private IUnitOfWork unitOfWork;
private ISession session;
public PersonSynchronizer(IUnitOfWork uow) {
this.unitOfWork = uow;
this.session = unitOfWork.Session;
}
public Dictionary<string, Person> GetPersons(IEnumerable<string> wurAccounts) {
var accounts = wurAccounts.ToList();
return this.session.Query<Person>()
.Where(x => accounts.Contains(x.WurAccount))
.ToDictionary(x => x.WurAccount);
}
}
public class Person {
public string DisplayName { get; set; }
public string Email { get; set; }
public string WurAccount { get; set; }
}
public interface IUnitOfWork : IDisposable {
ISession Session { get; }
IQueryable<T> Query<T>();
void BeginTransaction();
void Commit();
void Rollback();
}
public interface ISession {
IQueryable<T> Query<T>();
}
}
The snippet above passes as expected when tested.
I suggest reviewing if there are any NHibernate extension methods being called that may be conflicting with the default Linq Extensions, causing the issues encountered.
Related
I have a strange issue.
I am creating a generic class and I have a generic method and test. The test looks like this:
[Test]
public async Task ReturnGeneric()
{
// Assemble
const int id = 1;
var request = new GetGeneric<Venue>(id);
var services = GetGenericContext.GivenServices();
var handler = services.WhenCreateHandler();
var venues = Builder<Venue>.CreateListOfSize(20).Build().ToDbSet();
services.DatabaseContext.Set<Venue>().Returns(venues);
// Act
var response = await handler.Handle(request, CancellationToken.None);
// Assert
response.Success.Should().BeTrue();
response.Error.Should().BeNull();
response.Result.Should().BeOfType<Venue>();
}
}
And the method looks like this:
public async Task<Attempt<T>> Handle(GetGeneric<T, TKey> request, CancellationToken cancellationToken)
{
var id = request.Id;
if (EqualityComparer<TKey>.Default.Equals(id, default)) return ValidationError.Required(nameof(id));
var generics = _databaseContext.Set<T>().AsQueryable();
var t = _databaseContext.Set<T>().ToList();
var generic = generics.SingleOrDefault(m => m.Id.Equals(request.Id));
var x = t.SingleOrDefault(m => m.Id.Equals(id));
if (generic == null) return NotFoundError.ItemNotFound(nameof(T), request.Id.ToString());
return generic;
}
variables t and x are just tests for my own sanity.
The issue here is that generic is null in my test, but x is not.
It seems to have a problem with the AsQueryable() method. For some reason if I do a call to AsQueryable() there are no results in the collection, but there are if it invoke ToList().
This is my extension method for ToDbSet():
public static class DbSetExtensions
{
public static DbSet<T> ToDbSet<T>(this IEnumerable<T> data) where T : class
{
var queryData = data.AsQueryable();
var dbSet = Substitute.For<DbSet<T>, IQueryable<T>>();
((IQueryable<T>)dbSet).Provider.Returns(queryData.Provider);
((IQueryable<T>)dbSet).Expression.Returns(queryData.Expression);
((IQueryable<T>)dbSet).ElementType.Returns(queryData.ElementType);
((IQueryable<T>)dbSet).GetEnumerator().Returns(queryData.GetEnumerator());
return dbSet;
}
}
Can anyone think of a reason why this is not working?
The entire class looks like this:
public class GenericGet<T, TKey> : IRequest<Attempt<T>> where T: TClass<TKey>
{
public TKey Id { get; }
public GenericGet(TKey id)
{
Id = id;
}
}
public class GenericGet<T> : GenericGet<T, int> where T : TClass<int>
{
public GenericGet(int id) : base(id)
{
}
}
public class GenericGetHandler<T, TKey> : IRequestHandler<GenericGet<T, TKey>, Attempt<T>> where T: TClass<TKey>
{
private readonly DatabaseContext _databaseContext;
public GenericGetHandler(DatabaseContext databaseContext)
{
_databaseContext = databaseContext;
}
public async Task<Attempt<T>> Handle(GenericGet<T, TKey> request, CancellationToken cancellationToken)
{
var id = request.Id;
if (EqualityComparer<TKey>.Default.Equals(id, default)) return ValidationError.Required(nameof(id));
var generics = _databaseContext.Set<T>().AsQueryable();
var generic = generics.SingleOrDefault(m => m.Id.Equals(request.Id));
if (generic == null) return NotFoundError.ItemNotFound(nameof(T), request.Id.ToString());
return generic;
}
}
public class GenericGetHandler<T> : GenericGetHandler<T, int> where T : TClass<int>
{
public GenericGetHandler(DatabaseContext databaseContext) : base(databaseContext)
{
}
}
And a venue looks like this:
public class Venue: TClass<int>
{
[Required, MaxLength(100)] public string Name { get; set; }
[MaxLength(255)] public string Description { get; set; }
public IList<Theatre> Theatres { get; set; }
}
I changed my DatabaseContext mock to actually use the in memory provider as suggested by Fabio.
It looks like this:
public class DatabaseContextContext
{
public DatabaseContext DatabaseContext;
protected DatabaseContextContext()
{
var options = new DbContextOptionsBuilder<DatabaseContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.EnableSensitiveDataLogging()
.Options;
DatabaseContext = new DatabaseContext(options);
}
}
And then my GetGenericContext looks like this:
public class GenericGetContext<T> : DatabaseContextContext where T : TClass<int>
{
public static GenericGetContext<T> GivenServices() => new GenericGetContext<T>();
public GenericGetHandler<T> WhenCreateHandler() => new GenericGetHandler<T>(DatabaseContext);
}
Instead of doing:
services.DatabaseContext.Set<Venue>().Returns(venues);
We are not mocking anymore, so we can actually do:
services.DatabaseContext.Venues.AddRange(venues);
services.DatabaseContext.SaveChanges();
We must call save changes otherwise it won't actually say the venues to the collection.
Once you do that, everything works as expected.
I'm wondering if I can do a global config for a test. I know that I can compare this object something like that:
x.Should().BeEquivalentTo(y, opt => opt.Excluding(z => z.Member)
But I want all the methods in my test to use this config.
To exclude a member from a specific type, you can create a custom IMemberSelectionRule.
To use that selection rule for all tests, use the static AssertionOptions.AssertEquivalencyUsing in some setup method of your unit testing framework.
Be aware that AssertionOptions.AssertEquivalencyUsing changes static state of Fluent Assertions, so if you're running tests in parallel it should be invoked before any tests are run.
For NUnit that would be [OneTimeSetUp] inside a [SetUpFixture] not inside a namespace.
using FluentAssertions;
using FluentAssertions.Equivalency;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
[SetUpFixture]
public class MySetUpClass
{
[OneTimeSetUp]
public void RunBeforeAnyTests()
{
AssertionOptions.AssertEquivalencyUsing(e => e.Using(new MyNamespace.MyClassSelectionRule()));
}
}
namespace MyNamespace
{
class MyOuterClass
{
public MyInnerClass MemberToInclude { get; set; }
public int MemberToExclude { get; set; }
}
class MyInnerClass
{
public int AnotherMemberToInclude { get; set; }
public int MemberToExclude { get; set; }
}
internal class MyClassSelectionRule : IMemberSelectionRule
{
public bool IncludesMembers => false;
public IEnumerable<SelectedMemberInfo> SelectMembers(IEnumerable<SelectedMemberInfo> selectedMembers, IMemberInfo context, IEquivalencyAssertionOptions config) =>
selectedMembers.Where(e => !(e.DeclaringType.Name == nameof(MyOuterClass) && e.Name == nameof(MyOuterClass.MemberToExclude)));
}
[TestFixture]
public class UnitTest1
{
[Test]
public void Ignore_the_member_MemberToExclude_on_MyOuterClass()
{
var subject = new MyOuterClass
{
MemberToInclude = new MyInnerClass
{
AnotherMemberToInclude = 42,
MemberToExclude = 42
},
MemberToExclude = 1
};
var expectation = new MyOuterClass
{
MemberToInclude = new MyInnerClass
{
AnotherMemberToInclude = 42,
MemberToExclude = 42
},
MemberToExclude = 2
};
subject.Should().BeEquivalentTo(expectation);
}
[Test]
public void Do_not_ignore_the_member_MemberToExclude_on_MyInnerClass()
{
var subject = new MyOuterClass
{
MemberToInclude = new MyInnerClass
{
MemberToExclude = 1
},
};
var expectation = new MyOuterClass
{
MemberToInclude = new MyInnerClass
{
MemberToExclude = 2
},
};
Action act = () => subject.Should().BeEquivalentTo(expectation);
act.Should().Throw<AssertionException>();
}
}
}
I am trying to understand a behavior that is occurring in my application. I have mocked out my DbContext and when I make a call get items from the dbContext.Set<T>().ToList(), the second call does not contain my mocked data. I am not sure why this happens since that data should still exist. Please see code below:
SUT:
public class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public decimal Salary { get; set; }
}
public class EmployeeDb
: DbContext
{
public EmployeeDb()
{
}
public virtual IDbSet<Employee> Employees { get; set; }
}
UNIT TEST:
public class MockDatabase
{
public Mock<EmployeeDb> SetMockData()
{
var mockDb = new Mock<EmployeeDb>();
mockDb.Setup(i => i.Set<Employee>()).Returns(GetMockSet(Employees).Object);
mockDb.SetupGet(i => i.Employees).Returns(() => GetMockSet(Employees).Object);
return mockDb;
}
private List<Employee> _providers;
private List<Employee> Employees => _providers ?? (_providers = new List<Employee>
{
GetEmployee(1),
GetEmployee(2),
GetEmployee(3),
GetEmployee(4),
GetEmployee(5),
});
private static Employee GetEmployee(int id)
{
return new Employee
{
FirstName = Faker.Name.First(),
LastName = Faker.Name.Last(),
Age = Faker.RandomNumber.Next(50),
Id = id,
Salary = Faker.RandomNumber.Next(100000)
};
}
#region Hood
public static Mock<DbSet<T>> GetMockSet<T>(IList<T> items) where T : class
{
var querable = items.AsQueryable();
var mockSet = new Mock<DbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(querable.Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(querable.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(querable.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(querable.GetEnumerator());
mockSet.Setup(i => i.Add(It.IsAny<T>())).Callback(delegate (T item) {
items.Add(item);
});
return mockSet;
}
#endregion
}
[TestClass]
public class UnitTest1
{
private EmployeeDb _context;
[TestInitialize]
public void TestInitialize()
{
var mockDb = new MockDatabase();
_context = mockDb.SetMockData().Object;
}
[TestMethod]
public void Test_CallTwice_ReturnsEqualCount()
{
var emps = _context.Set<Employee>().ToList();
var emps2 = _context.Set<Employee>().ToList();
Assert.IsTrue(emps.Count == emps2.Count);
// -- This works
//var empCount = _context.Set<Employee>().Count();
//var empCount2 = _context.Set<Employee>().Count();
//Assert.IsTrue(empCount == empCount2);
}
}
Is there something I am not getting about this code? Is there something Moq does with the ToList()?
ToList enumerates the set when invoked, but the enumerator is forward only, so after the first call it is already at the end.
When setting up the GetEnumerator use the function overload of the Returns in order to allow multiple calls other wise the same enumerator will be returned every time and you get the behavior you experienced.
mockSet.As<IQueryable<T>>()
.Setup(m => m.GetEnumerator())
.Returns(() => querable.GetEnumerator()); //<-- function
is it possible?
Public String Get_Filed_By_Id(string table_Name,String Field_Name,string PK_val)
{
string strRes="";
using(mydbcontext db=new mydbcontext())
{
var x=db.table_Name.Where(p=>p.Id=PK_val).FirstOrDefault().Field_Name;
strRes=Convert.Tostring(x);
}
return strRes;
}
OR
var x=(from o in db.table_Name where o.Id=PK_val select o.Field_Name).FirstOrDefault();
Here, i'm passing Table_Name,Column_Name and the Condition value(PK_val) to Get the Column_Name from Table_Name within a Certain Condition(Id=Pk_val).
Is it possible??
Is it possible??
Yes, it is.
First, some helpers:
using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
namespace YourNamespace
{
internal static class DbHelpers
{
public static object GetColumnById(this object dbContext, string tableName, string columnName, object id)
{
var table = (IQueryable)dbContext.GetType().GetProperty(tableName).GetValue(dbContext, null);
var row = Expression.Parameter(table.ElementType, "row");
var filter = Expression.Lambda(Expression.Equal(Expression.Property(row, "Id"), Expression.Constant(id)), row);
var column = Expression.Property(row, columnName);
var selector = Expression.Lambda(column, row);
var query = Call(Where.MakeGenericMethod(row.Type), table, filter);
query = Call(Select.MakeGenericMethod(row.Type, column.Type), query, selector);
var value = Call(FirstOrDefault.MakeGenericMethod(column.Type), query);
return value;
}
private static readonly MethodInfo Select = GetGenericMethodDefinition<
Func<IQueryable<object>, Expression<Func<object, object>>, IQueryable<object>>>((source, selector) =>
Queryable.Select(source, selector));
private static readonly MethodInfo Where = GetGenericMethodDefinition<
Func<IQueryable<object>, Expression<Func<object, bool>>, object>>((source, predicate) =>
Queryable.Where(source, predicate));
private static readonly MethodInfo FirstOrDefault = GetGenericMethodDefinition<
Func<IQueryable<object>, object>>(source =>
Queryable.FirstOrDefault(source));
private static MethodInfo GetGenericMethodDefinition<TDelegate>(Expression<TDelegate> e)
{
return ((MethodCallExpression)e.Body).Method.GetGenericMethodDefinition();
}
private static object Call(MethodInfo method, params object[] parameters)
{
return method.Invoke(null, parameters);
}
}
}
and now your function:
public string Get_Field_By_Id(string table_Name, string field_Name, string PK_val)
{
using (var db = new mydbcontext())
return Convert.ToString(db.GetColumnById(table_Name, field_Name, PK_val));
}
It is not really possible with EntityFramework actually(as far as I know). If you only needed the field by its name, then you could have used #Den's proposed solution. But you want to specify the table name too as a parameter. So I suggest you to use standard Sql Connector api, and build the query string with the parameters you provide.
Check this link for usage of standard sql connector api.
I had this question too ,I know this is not exactly what you want and you need write more code but it's much cleaner than those you want to write.
Using repository pattern
For every table you should have a model class and Repository class.
Consider this code(this code from one of my project)
This is my comment table(this can be anything with or without navigation property)
public sealed class Comment
{
public string CommentText { get; set; }
public DateTime PostDate { get; set; }
public int PostId { get; set; }
public int? PageId { get; set; }
public Page Page { get; set; }
public User User { get; set; }
public string UserId { get; set; }
public int? ParentId { get; set; }
public Comment[] ChildComments { get; set; }
}
RepositoryComment
public sealed class CommentRepository : BaseRepository<Comment>
{
public CommentRepository(BabySitterContext context)
: base(context)
{
}
}
and a base class that you send your query with table name(here model) and field(you can extend clas for more functionality)
public class BaseRepository<T> where T : class
{
protected BabySitterContext Context;
private readonly PluralizationService _pluralizer = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en"));
public BaseRepository(BabySitterContext context)
{
this.Context = context;
}
public bool Add(T t)
{
Context.Set<T>().Add(t);
Context.SaveChanges();
return true;
}
public bool Update(T t)
{
var entityName = GetEntityName<T>();
object originalItem;
var key = ((IObjectContextAdapter)Context).ObjectContext.CreateEntityKey(entityName, t);
if (((IObjectContextAdapter)Context).ObjectContext.TryGetObjectByKey(key, out originalItem))
{
((IObjectContextAdapter)Context).ObjectContext.ApplyCurrentValues(key.EntitySetName, t);
}
Context.SaveChanges();
return true;
}
public void Attach(T t)
{
if (t == null)
{
throw new ArgumentNullException("t");
}
Context.Set<T>().Attach(t);
Context.SaveChanges();
}
public void Remove(T t)
{
if (t == null)
{
throw new ArgumentNullException("t");
}
Context.Set<T>().Remove(t);
Context.SaveChanges();
}
public IEnumerable<T> Get(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "")
{
IQueryable<T> query = Context.Set<T>();
if (filter != null)
{
query = query.Where(filter.Expand());
}
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
private string GetEntityName<TEntity>() where TEntity : class
{
return string.Format("{0}.{1}", ((IObjectContextAdapter)Context).ObjectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name));
}
public virtual IEnumerable<T> GetByBusinessKey(T entity)
{
return null;
}
}
For any other table just make model class and reposiotry then inherite from base class
Using code
var context = new BabySitterContext();
var _commentRepository = new CommentRepository(context);
var comment = _commentRepository.Get(x => x.PostId == id).FirstOrDefault();
No, but in this way
Public String Get_Filed_By_Id(string table_Name,String Field_Name,string PK_val)
{
string strRes="";
using(mydbcontext db=new mydbcontext())
{
var x=db.table_Name.Where(p=>p.Id=PK_val).Select(b=>b.Field_Name).FirstOrDefault();
strRes=Convert.Tostring(x);
}
return strRes;
}
I have the following code:
_eventInstanceRepository.GetInnerCollection().Update(
Query.EQ("_id", listingEventModel.Id),
Update.PushWrapped<string[]>("ArtistIds", ids.ToArray()));
Which is designed to update the following document:
public class ListingEvent
{
public ObjectId Id { get; set; }
public string[] ArtistIds { get; set; }
}
ids is a List
Any ideas why this isn't updating the docs?
[UPDATE]
Also tried this!
foreach (var id in ids)
{
_eventInstanceRepository.GetInnerCollection().Update(
Query.EQ("_id", listingEventModel.Id),
Update.Push("ArtistIds", id));
}
No luck...
[UPDATE]
Going back to RavenDb - at least for now. I don't see how MongoDb is a viable option the whole time there are no real sources discussing (slightly more complex than flat structure) document updates on the internet and the examples I can find simply do not work.
[UPDATE]
Here is the repository code:
public class Repository<T> : IRepository<T>
{
private readonly MongoCollection<T> _docs;
public Repository(MongoCollection<T> docs)
{
_docs = docs;
}
public IList<T> GetAll()
{
return _docs.FindAll().Select<T, T>(x => x.As<T>()).ToList();
}
//HACK!
public MongoCollection<T> GetInnerCollection(){
return _docs;
}
public void Save(T doc)
{
_docs.Save(doc);
}
public void Save(IEnumerable<T> docsToSave)
{
foreach (var doc in docsToSave) Save(doc);
}
public void Dispose()
{
throw new NotImplementedException();
}
public void Delete(string id)
{
var query = Query.EQ("_id", id);
_docs.Remove(query);
}
}
Working sample code for appending a list of strings to an existing list of strings using a strongly-typed Push:
class Event
{
public ObjectId Id { get; set; }
public string Name { get; set; }
public List<string> Participants { get; set; }
}
class Program
{
static void Main(string[] args)
{
MongoClient client = new MongoClient("mongodb://localhost/test");
var db = client.GetServer().GetDatabase("test");
var collection = db.GetCollection("events");
var event0 = new Event { Name = "Birthday Party",
Participants = new List<string> { "Jane Fonda" } };
collection.Insert(event0);
collection.Update(Query.EQ("_id", event0.Id),
Update<Event>.PushAll(p => p.Participants,
new List<string> { "John Doe", "Michael Rogers" }));
}
}