How to Unit Test without Hitting Database - c#

I want to ask what is a good unit test for the method below GetMeetingsByInterimIdentifier where interim identifier is a string -- such as 78th2015.
We are setup to use the interface IMeetingsService. We are using MOQ and Microsoft.VisualStudio.TestTools.UnitTesting.
public class MeetingsService : IMeetingsService
{
private readonly IInterimCommitteeDbContext _db;
public MeetingsService(IInterimCommitteeDbContext db)
{
this._db = db;
}
public IQueryable<Meeting> GetMeetingsByInterimIdentifier(string interimIdentifier)
{
return
from m in this._db.Meetings
join c in this._db.Committees on m.CommitteeId equals c.CommitteeId
where c.InterimIdentifier == interimIdentifier
select m;
}
public Meeting GetMeeting(int meetingKey)
{
return this._db.Meetings.FirstOrDefault(x => x.MeetingId == meetingKey);
}
}
Edit:
But I am not sure how to set it up. This result is not null, but what does it do for me?
[TestMethod]
public void GetMeetingsByInterimIdentifier_WithInterimIdentifier_ReturnsMeetingList()
{
//Arrange
var interim = Properties.Settings.Default.DefaultInterimIdentifier;
var result = _meetingServiceMock.Setup(x => x.GetMeetingsByInterimIdentifier(interim));
//Act
//Assert
Assert.IsNotNull(result);
}

Create a Mock<IInterimCommitteeDbContext> and pass it into the constructor. On this object setup the Meetings and Committees properties to return various collections.
You should have different tests setup that return different collections. For example, how should this behave if both the Meetings and Committees are empty, i.e. there is no data in the database? How should it behave if there isn't an object with the provided InterimIdentifier? What about if there is one that matches etc.

I figured out how to do this using test doubles. I am using Entity Framework 6 with the code first model. I created a DbContext that inherited from my I-DbContext interface. Then I was able to create in-memory data to use in my service layer unit tests. Below is an example of:
the test data context,
the test dbset,
an example unit test.
This solution was available from an msdn article here:
https://msdn.microsoft.com/en-us/data/dn314429.aspx
...
public class CommitteeContextTest : ICommitteeDbContext
{
public CommitteeContextTest()
{
this.Committees = new TestDbSet();
this.CommitteeMembers = new TestDbSet();
}
public Database Database { get; }
public DbSet Committees { get; set; }
public DbSet CommitteeMembers { get; set; }
}
}
public class TestDbSet : DbSet, IQueryable, IEnumerable, IDbAsyncEnumerable
where TEntity : class
{
ObservableCollection _data;
IQueryable _query;
public TestDbSet()
{
_data = new ObservableCollection();
_query = _data.AsQueryable();
}
public override TEntity Add(TEntity item)
{
_data.Add(item);
return item;
}
public override TEntity Remove(TEntity item)
{
_data.Remove(item);
return item;
}
public override TEntity Attach(TEntity item)
{
_data.Add(item);
return item;
}
public override TEntity Create()
{
return Activator.CreateInstance();
}
}
[TestClass]
public class CommitteeServiceTest
{
private InterimCommitteeContextTest _interimCommitteeContext;
private ICommitteeService _service;
private string _interim;
[TestInitialize]
public void SetUp()
{
_interimCommitteeContext = new InterimCommitteeContextTest();
_service = new CommitteeService(_interimCommitteeContext);
_interim = Settings.Default.DefaultInterimIdentifier;
}
[TestCleanup]
public void Teardown()
{
_interimCommitteeContext = null;
_service = null;
}
[TestMethod]
public void GetCommittee_ProvideInterimCommitteeId_ReturnOneCommittee()
{
//Arrange
AddCommittees();
//Act and Assert
var result = _service.GetCommittee(_interim, 1);
Assert.AreEqual(1, result.CommitteeId); //Passes. IsActive set to true;
result = _service.GetCommittee(_interim, 0);
Assert.IsNull(result); //Fails. No committeeId = 0;
result = _service.GetCommittee(_interim, 2);
Assert.IsNull(result); //Fails. CommitteeId = 2 is not active.
}
[TestMethod]
public void AddCommittees()
{
_interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 1, InterimIdentifier = _interim, IsActive = true, CommitteeTypeId = 1 });
_interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 2, InterimIdentifier = _interim, IsActive = false, CommitteeTypeId = 1 });
_interimCommitteeContext.Committees.Add(new Committee() { CommitteeId = 3, InterimIdentifier = _interim, IsActive = true, CommitteeTypeId = 1 });
}
}

Use Mocking, that's what it is for. Use JMock or Mockito or any other library you prefer.

Related

Unit test singletons

I have a singleton class and I want to run some unit tests in isolation. The problem is that all the tests run on the same instance and affect the expected results. Is there a workaround? I am using .net 6 and NUnit 3. Here's my code,
public interface ISingletonModel<T>
{
void AddValue(string key, T value, LinkedListNode node);
}
public sealed class SingletonModel<T> : ISingletonModel<T>
{
public Dictionary<string, (LinkedListNode<string> node, T value)> ModelDictionary { get; set; }
private static readonly Lazy<SingletonModel<T>> singletonModel=
new Lazy<SingletonModel<T>>(() => new SingletonModel<T>());
public static SingletonModel<T> Instance
{
get
{
return SingletonModel.Value;
}
}
private SingletonModel()
{
ModelDictionary = new Dictionary<string, (node, T value)>();
}
}
public void AddValue(string key, T value, LinkedListNode node)
{
if (ModelDictionary.ContainsKey(key))
{
var linkedListNode = ModelDictionary[key];
ModelDictionary[key] = (node, value);
}
else
{
ModelDictionary.Add(key, (node.AddFirst(key), value));
}
}
}
And some unit tests
private TestClass[] testData;
private IFixture fixture;
private SingletonModel<TestClass> model;
[SetUp]
public void Setup()
{
this.testData = GenerateTestData();
this.model= SingletonModel<TestClass>.Instance;
}
[Test]
public void CheckModelCapacity_ShouldReturnTheCorrectItems()
{
/ Act
foreach (var entity in testData)
{
this.model.AddValue(entity.Id, entity, entity.node);
}
IEnumerable<string> expected = new[] { "8", "3", "5", "2", "79" };
var actual = this.model.ModelDictionary.Keys.ToList();
// Assert
Assert.That(expected.OrderBy(x => x).SequenceEqual(actual.OrderBy(x => x)));
}
[Test]
public void CheckTotalItems_ShouldReplaceItemsWithTheSameKey()
{
// Assign
var entity1 = fixture.CreateMany(20);
// Act
foreach (var item in entity1)
{
this.model.AddValue(item.Id, item, item.node);
}
//Assert
Assert.AreEqual(2, this.model.ModelDictionary.Count);
}
Because of the singleton the tests are holding the values from the previous tests.
A public or internal constructor would allow for creating isolated instances in tests, but if the intention here is to not modify the current class then reflection can be used to access the private constructor to create isolated instances for tests.
Here is a simplified model based on the original since it was incomplete and wouldn't compile.
public interface ISingletonModel<T> {
void AddValue(string key, T value);
int Count { get; }
}
public sealed class SingletonModel<T> : ISingletonModel<T> {
Dictionary<string, T> dictionary;
private static readonly Lazy<SingletonModel<T>> singletonModel = new Lazy<SingletonModel<T>>(() => new SingletonModel<T>());
public static SingletonModel<T> Instance => singletonModel.Value;
private SingletonModel() {
dictionary = new Dictionary<string, T>();
}
public void AddValue(string key, T value) => dictionary[key] = value;
public int Count => dictionary.Count;
}
Using one of the overloads of Activator.CreateInstance:
Activator.CreateInstance(Type type, bool nonPublic)
which uses reflection to access the private constructor, shows that instances can be created to be tested in isolation
public class Program {
public static void Main() {
//Arrange
int expected = 1;
ISingletonModel<int> model1 = (ISingletonModel<int>)Activator.CreateInstance(typeof(SingletonModel<int>), true);
//Act
model1.AddValue("one", 1);
//Assert
int actual = model1.Count;
Console.WriteLine($"{actual}, As expected: {actual == expected}");
//Arrange
expected = 3;
ISingletonModel<int> model2 = (ISingletonModel<int>)Activator.CreateInstance(typeof(SingletonModel<int>), true);
//Act
model2.AddValue("one", 1);
model2.AddValue("two", 2);
model2.AddValue("three", 3);
//Assert
actual = model2.Count;
Console.WriteLine($"{actual}, As expected: {actual == expected}");
//Arrange
expected = 2;
ISingletonModel<int> model3 = (ISingletonModel<int>)Activator.CreateInstance(typeof(SingletonModel<int>), true);
//Act
model3.AddValue("one", 1);
model3.AddValue("two", 2);
//Assert
actual = model3.Count;
Console.WriteLine($"{actual}, As expected: {actual == expected}");
}
}
which return the following output
1, As expected: True
3, As expected: True
2, As expected: True
Add ResetForTesting() method your singleton class?

XUnit before all (fixture) doesn't work for me

I'm trying to fill the In-Memory database with 3 data objects. I'm using a fixture for that purpose.
My Fixture :
public class UBSeedDataFixture : IDisposable
{
public AzDbContext DBContext { get; private set; }
public UBSeedDataFixture()
{
var options = new DbContextOptionsBuilder<AzDbContext>()
.UseInMemoryDatabase(databaseName: "InMemoryTestDb")
.Options;
DBContext = new AzDbContext(options);
DBContext.UBs.Add(new UB { Title = "UB1", Code = "SomeCode" });
DBContext.UBs.Add(new UB { Title = "UB2", Code = "SomeCode" });
DBContext.UBs.Add(new UB { Title = "UB3", Code = "SomeCode" });
DBContext.SaveChanges();
}
public void Dispose()
{
DBContext.Database.EnsureDeleted();
DBContext.Dispose();
}
}
then I run two simple tests:
public class UBTests : IClassFixture<UBSeedDataFixture>
{
UBSeedDataFixture fixture;
public UBTests(UBSeedDataFixture fixture)
{
this.fixture = fixture;
}
[Fact]
public void DeleteTest()
{
var result = fixture.DBContext.UBs.SingleOrDefault(u => u.Title == "UB1");
fixture.DBContext.Remove(result);
fixture.DBContext.SaveChanges();
result = fixture.DBContext.UBs.SingleOrDefault(u => u.Title == "UB1");
Assert.Equal(null, result);
}
[Fact]
public void AddTest()
{
var ubs = fixture.DBContext.UBs.ToList();
Assert.Equal("UB1", ubs[0].Title);
}
}
As the result, I get an error that I get more than one result when I query data with Title == "UB1". If I debug my tests I have 6 elements in my database, when my fixture is supposed to create only 3. It seems like my fixture runs every time when a new test runs. How can I fix it so I have a fixture something like "Once before all tests"?

Using DI with Entity Framework and multiple data contexts in ASP.NET MVC

I am wondering, how we can handle a situation, and if I'm going about this the wrong way. We wrote a web application based on one ERP's database schema model. We are using Entity Framework for the system, with the regular dependency injection method.
Now that we have purchased multiple ERP's from other labs, we are trying to allow their data be used on our first original web portal built for our original ERP. As you can imagine, this is rough as the database models and design will not line up with ours. For example something like GetAllAssets() stored procedure returns the complex type and then is bound to the repo level, the service level and onto the view.
What I was thinking is that we could maybe add multiple EDMX (context for databases), then keep everything from the Views to the controllers to the service layer the same. At the service layer, and type params to our classes, and so we could pass the context the current user logged in as, and then in auto mapper add new entries for the new database context calls from Entity Framework, to map to our original code from the service back down to the view.
Is this possible, and or a good idea or bad idea?
Here is a example of a current basic controller we are using with DI style, and I have removed a lot of code for this question's example:
[AuthorizeWithSession]
public class LocationController : Controller
{
private readonly IMProAssetLocationService _mProAssetLocationService;
private readonly IUIDataService _uiDataService;
public LocationController(IMProAssetLocationService mProAssetLocationService,
IUIDataService uiDataService)
{
_mProAssetLocationService = mProAssetLocationService;
}
public ActionResult List()
{
return View();
}
public ActionResult List2()
{
return View();
}
public ActionResult GetLocationList([DataSourceRequest]DataSourceRequest request)
{
//var result = DepartmentService.GetDepartmentList(SessionHelper.GetCustId());
var result = _mProAssetLocationService.MProAssetLocationGetLocationByCustID(SessionHelper.GetCustId(), null);
if (result != null && result.Any())
{
return Json(result.ToDataSourceResult(request), JsonRequestBehavior.AllowGet);
}
}
}
The interface service layer:
public interface IMProAssetLocationService
{
IEnumerable<LocationVm> MProAssetLocationGetLocationByCustID(string custId,string id);
string MProAssetLocationInsertLocation(LocationVm vm);
void MProAssetLocationDeleteLocationByCustIDAndLocationID(string custId, string locationId);
void MProAssetLocationUpdateLocationByCustIDAndLocationID(LocationVm vm);
}
The service layer:
public class MProAssetLocationService : LogManager, IMProAssetLocationService
{
private readonly IMProAssetLocationRepo _mProAssetLocationRepo;
public MProAssetLocationService(IMProAssetLocationRepo mProAssetLocationRepo)
{
_mProAssetLocationRepo = mProAssetLocationRepo;
}
protected override Type LogPrefix
{
get { return this.GetType(); }
}
public IEnumerable<LocationVm> MProAssetLocationGetLocationByCustID(string custId, string id)
{
List<LocationVm> listlocationVm = new List<LocationVm>();
try
{
var records = _mProAssetLocationRepo.MProAssetLocationGetLocationByCustID(custId,id);
}
}
The Interface repo layer:
public interface IMProAssetLocationRepo : IRepository<MProAssetLocation>
{
IEnumerable<string> GetMProAssetLocatonByCustId(string custId);
IEnumerable<string> GetMProAssetLocatonDescriptionByCustId(string custId);
IEnumerable<LocationView> GetMProAssetLocatonListByCustId(string search, string locationID, string custId);
IEnumerable<LocationView> MProAssetLocationGetLocationByCustID(string custId, string id);
string MProAssetLocationInsertLocation(LocationView lv);
void MProAssetLocationDeleteLocationByCustIDAndLocationID(string custId, string locationId);
void MProAssetLocationUpdateLocationByCustIDAndLoacationID(LocationView lv);
}
The repo layer:
public class CalLocationsRepo : RepositoryBase<CalLocaton>, ICalLocationsRepo
{
public CalLocationsRepo(IDbFactory dbFactory)
: base(dbFactory)
{
}
//WHERE CalCodeActive=1 AND CalCodeGroup='OSS' ORDER BY CalCode
public IEnumerable<string> GetCalLocations(string empID)
{
return DbContext.TAM_GetCalLocationsList(empID).ToList();
}
}
I was thinking of something like using a context type in our system. I know the entity models calls would be named differently based on our different databases using their own stored procedures, but thought at the level prior to the call i check the context to use, then make the call accordingly like so:
public class DBContextRepo<T> : RepositoryBase, IDBContextRepo<T>
{
DBContextRepo<T> _typeParameterClass;
public DBContextRepo(IDbFactory dbFactory, DBContextRepo<T> typeParameterClass)
: base(dbFactory)
{
_typeParameterClass = typeParameterClass;
}
public List<string> GetAllModelsByManufcaturer(string manufacturerName)
{
List<string> results = new List<string>();
if (_typeParameterClass.GetType() == typeof(TAM.DataLayer.EntityModels.QuoteWerks1Entities))
{
using(var dbContext = DbContextQw)
{
var items = dbContext.Products_OurProducts_Products.Where(p => p.Manufacturer == manufacturerName).ToList();
results = items.Select(p => p.ManufacturerPartNumber).ToList();
}
}
else
{
using (var dbContext = DbContext)
{
var items = dbContext.Models.Where(a => a.Manufacturer.MfrName == manufacturerName);
results = items.Select(m => m.ModelNumber).ToList();
}
}
return results;
}
}
This causes errors and is where im not sure how to handle two DBContext:
public class DbFactory : Disposable, IDbFactory
{
private TAMModel _dbContext;
private QuoteWerks1Entities _dbContextQW;
public TAMModel Init()
{
return _dbContext ?? (_dbContext = new TAMModel());
}
public QuoteWerks1Entities InitQW()
{
return _dbContextQW ?? (_dbContextQW = new QuoteWerks1Entities());
}
protected override void DisposeCore()
{
if (_dbContext != null)
{
_dbContext.Dispose();
}
if (_dbContextQW != null)
{
_dbContextQW.Dispose();
}
}
}
Once i added the second context, all of my regular code say they do not have a corresponding type in constructors such as this one:
public class ContractRepo : RepositoryBase<Contract>, IContractRepo
{
public ContractRepo(IDbFactory dbFactory)
: base(dbFactory)
{
}
public string GetContractIdentifyByCustId(string custId)
{
return DbContext.TAM_GetContractIdentifyByCustId(custId).SingleOrDefault();
}
}
Here is the BaseRepo class:
public class RepositoryBase
{
private readonly TAMModel _dataContext;
private readonly QuoteWerks1Entities _dataContextQW;
protected IDbFactory DbFactory { get; private set; }
protected TAMModel DbContext
{
get
{
return _dataContext ?? DbFactory.Init();
}
}
protected QuoteWerks1Entities DbContextQw
{
get
{
return _dataContextQW ?? DbFactory.InitQW();
}
}
protected RepositoryBase(IDbFactory dbFactory)
{
DbFactory = dbFactory;
}
}
public abstract class RepositoryBase<T> where T : class
{
private readonly TAMModel _dataContext;
private readonly IDbSet<T> _dbSet;
private readonly IDbSet<T> _dbSetQW;
private readonly QuoteWerks1Entities _dataContextQW;
protected IDbFactory DbFactory { get; private set; }
protected TAMModel DbContext
{
get
{
return _dataContext ?? DbFactory.Init();
}
}
protected QuoteWerks1Entities DbContextQW
{
get
{
return _dataContextQW ?? DbFactory.InitQW();
}
}
protected RepositoryBase(IDbFactory dbFactory, T type)
{
DbFactory = dbFactory;
_dbSet = DbContext.Set<T>();
_dbSetQW = DbContextQW.Set<T>();
}
public virtual void Add(T entity)
{
_dbSet.Add(entity);
}
public virtual void Update(T entity)
{
_dbSet.Attach(entity);
DbContext.Entry(entity).State = EntityState.Modified;
}
public virtual void Delete(T entity)
{
_dbSet.Remove(entity);
}
public virtual void Delete(Expression<Func<T, bool>> where)
{
IEnumerable<T> objects = _dbSet.Where<T>(where);
foreach (T obj in objects)
{
_dbSet.Remove(obj);
}
}
public virtual T GetById(int id)
{
return _dbSet.Find(id);
}
public virtual T GetById(string id)
{
return _dbSet.Find(id);
}
public virtual IEnumerable<T> GetAll()
{
return _dbSet.ToList();
}
public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).ToList();
}
public T Get(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where).SingleOrDefault();
}
public virtual IQueryable<T> Query()
{
return _dbSet;
}
public virtual IQueryable<T> Query(Expression<Func<T, bool>> where)
{
return _dbSet.Where(where);
}
public virtual ObjectQuery<U> CreateQuery<U>(string query, ObjectParameter[] parameters)
{
return CastAsObjectContext().CreateQuery<U>(query, parameters);
}
public virtual ObjectQuery<U> CreateQuery<U>(string query)
{
return CreateQuery<U>(query, new ObjectParameter[0] { });
}
public virtual ObjectQuery<DbDataRecord> CreateQuery(string query, ObjectParameter[] parameters)
{
return CreateQuery<DbDataRecord>(query, parameters);
}
public virtual ObjectQuery<DbDataRecord> CreateQuery(string query)
{
return CreateQuery<DbDataRecord>(query);
}
private ObjectContext CastAsObjectContext()
{
var oContext = (DbContext as IObjectContextAdapter).ObjectContext;
return oContext;
}
}
The only problem is, how do I set the context on a login when using dependency injection? Will this work, as at the moment I'm still in the process, or am I over complicating it and going about it the wrong way? Thanks in advance.

Mock UnitOfWork interface with a Repository interface property

I am implementing a unit test to test a method in a helper class.
I have mocked my IRepository interface and passed its object to my mocked IUnitOfWork because this IRepository interface is a property to the UnitOfWork. While debugging the unit test, I found out that the call to '_unitOfWork.Booking.OverlappingBooking' in the helper class always return null. The OverlappingBooking()is not invoked at all.
public class BookingHelper
{
private IUnitOfWork _unitOfWork;
public BookingHelper(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public string OverlappingBookingsExist(Booking booking)
{
if (booking.Status == "Cancelled")
return string.Empty;
var bookings = _unitOfWork.Booking.GetActiveBookings<Booking>().Where(
b => b.Id != booking.Id && b.Status != "Cancelled");
var overlappingBooking = _unitOfWork.Booking.OverlappingBooking(bookings, booking);
return overlappingBooking;
}
}
my UnitOfWork
public interface IUnitOfWork
{
IBookingHelperRepository Booking { get; set; }
}
public class UnitOfWork: IUnitOfWork
{
public IBookingHelperRepository Booking { get; set; }
public UnitOfWork()
{
Booking = new BookingHelperRepository();
}
}
Repository
public interface IBookingHelperRepository
{
IQueryable<T> GetActiveBookings<T>();
string OverlappingBooking(IQueryable<Booking> bookings, Booking booking);
}
public class BookingHelperRepository: IBookingHelperRepository
{
public IQueryable<T> GetActiveBookings<T>()
{
var resp = new List<T>().AsQueryable();
return resp;
}
public string OverlappingBooking(IQueryable<Booking> bookings, Booking booking)
{
var overlappingBooking = bookings.FirstOrDefault(
b => booking.ArrivalDate >= b.ArrivalDate
&& booking.ArrivalDate < b.DepartureDate
|| booking.DepartureDate > b.ArrivalDate
&& booking.DepartureDate <= b.DepartureDate);
return overlappingBooking == null ? string.Empty : overlappingBooking.Reference;
}
}
I have set up my test class as below.
[TestClass]
public class BookingHelperTests
{
private Mock<IBookingHelperRepository> bookingHelperRepository;
private BookingHelper bookingHelper;
private Booking booking;
private Mock<IUnitOfWork> unitOfWork;
[TestInitialize]
public void Initialise()
{
unitOfWork = new Mock<IUnitOfWork>();
bookingHelper = new BookingHelper(unitOfWork.Object);
bookingHelperRepository = new Mock<IBookingHelperRepository>();
.....
}
[TestMethod]
public void OverlappingBookingsExist_BookingStartsAndFinishesBeforeAnExistingBooking_ShouldReturnEmptyString()
{
bookingHelperRepository.Setup(y => y.GetActiveBookings<Booking>()).Returns(bookingListBefore.AsQueryable());
unitOfWork.Setup(x => x.Booking).Returns(bookingHelperRepository.Object);
//Act
var result = bookingHelper.OverlappingBookingsExist(booking);
//Assert
Assert.AreEqual("", result);
}
The code you want to test calls (IBookingHelperRepository)(IUnitOfWork.Booking).OverlappingBooking(), which you don't mock. Because mocks are loose by default, they return null instead of throwing an exception.
If you'd set up new Mock<IBookingHelperRepository>() with MockBehavior.Strict, you'd receive an exception telling you that you haven't set up the method string OverlappingBooking(IQueryable<Booking> bookings, Booking booking).
In order to do so:
var queryableBookings = bookingListBefore.AsQueryable();
bookingHelperRepository.Setup(y => y.GetActiveBookings<Booking>()).Returns(queryableBookings);
bookingHelperRepository.Setup(y => y.OverlappingBooking(queryableBookings, booking).Returns(booking.Reference);

ASP.NET and MongoDB - Not saving in the context of a Unit Test

I am new to MongoDB and setting up a .NET C# MVC Project to try it out.
Using the current MongoDB.Driver 2.2.2 from nuget.
Issue:
I have a unit test that succeeds but does not save any data to the MongoDB Collection.
[TestMethod]
public void TestMethod1()
{
IDatabase<Publisher> context = new MyProject.Data.Concrete.MongoDatabase<Publisher>("Publishers");
Publisher pub = new Publisher()
{
Name = "Test"
};
context.Add(pub);
}
However, if I put this same test under a MVC Controller it will save the data:
public ActionResult Contact() {
ViewBag.Message = "Your contact page.";
IDatabase<Publisher> context = new MyProject.Data.Concrete.MongoDatabase<Publisher>("Publishers");
Publisher pub = new Publisher()
{
Name = "Test"
};
context.Add(pub);
return View();
}
I am curious as to why this is so?
Here is the MongoDatabase class:
public class MongoDatabase<T> : IDatabase<T> where T : class, new()
{
private static string _connectionString = ConfigurationManager.ConnectionStrings["mongodb"].ConnectionString;
private MongoClient _mongoClient = new MongoClient(_connectionString);
private string _collectionName;
private IMongoDatabase _db;
protected IMongoCollection<T> _collection
{
get
{
return _db.GetCollection<T>(_collectionName);
}
set
{
_collection = value;
}
}
public IQueryable<T> Query
{
get
{
return _collection.AsQueryable<T>();
}
set
{
Query = value;
}
}
public MongoDatabase(string collectionName)
{
_collectionName = collectionName;
_db = _mongoClient.GetDatabase(MongoUrl.Create(_connectionString).DatabaseName);
}
public bool Add(T item)
{
var result = _collection.InsertOneAsync(item);
//return result. what can we use here?
return true;
}
public int Add(IEnumerable<T> items)
{
int count = 0;
foreach (T item in items)
{
if (Add(item))
{
count++;
}
}
return count;
}
}
1) You should change calls for async methods.
public async Task Add(T item)
{
await _collection.InsertOneAsync(item);
}
You can read more about async.
2)
//return result. what can we use here?
return true;
You don't need to return bool. You need to have exception handler on a top level.

Categories

Resources