I don't know why this test fails. I created a new function, tested it manually and it works fine.
After that, I attempted to create test, but it always fails.
I don't know why.
It just should clear all records from DB older than 1,5 year, but variable historyToDelete always has 0 records. There is whole test:
using Microsoft.EntityFrameworkCore;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TeamsAllocationManager.Contracts.EmployeeWorkingTypeHistory;
using TeamsAllocationManager.Database;
using TeamsAllocationManager.Domain.Models;
using TeamsAllocationManager.Infrastructure.Handlers.EmployeeWorkingHistory;
namespace TeamsAllocationManager.Tests.Handlers.EmployeeWorkingHistory
{
[TestFixture]
public class ClearOldEmployeeWorkingTypeHistoryRecordsHandlerTest
{
private readonly ApplicationDbContext _context;
public ClearOldEmployeeWorkingTypeHistoryRecordsHandlerTest()
{
DbContextOptions<ApplicationDbContext> options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: GetType().Name)
.Options;
_context = new ApplicationDbContext(options);
}
[SetUp]
public void SetupBeforeEachTest()
{
_context.ClearDatabase();
var employeeWorkingTypeHistory1 = new EmployeeWorkingTypeHistoryEntity
{
EmployeeId = Guid.Parse("d6951ec1-c865-41bb-8b83-0fcd81745579"),
WorkspaceType = 0,
Created = new DateTime(2000, 01, 01)};
var employeeWorkingTypeHistory2 = new EmployeeWorkingTypeHistoryEntity
{
EmployeeId = Guid.Parse("8a6c4e1c-2c6d-4b70-a507-7bdae5f75429"),
WorkspaceType = 0,
Created = DateTime.Now
};
_context.EmployeeWorkingTypeHistory.Add(employeeWorkingTypeHistory1);
_context.EmployeeWorkingTypeHistory.Add(employeeWorkingTypeHistory2);
_context.SaveChanges();
}
[Test]
public async Task ShouldClearHistory()
{
// given
int numberOfHistoryToClear = 1;
int expectedInDatabase = _context.EmployeeWorkingTypeHistory.Count() - numberOfHistoryToClear;
var command = new ClearOldEmployeeWorkingTypeHistoryRecordsCommand();
var deletionDate = command.TodayDate.AddMonths(-18);
var historyToDelete = await _context.EmployeeWorkingTypeHistory
.Where(ewth => deletionDate > ewth.Created)
.ToListAsync();
var commandHandler = new ClearOldEmployeeWorkingTypeHistoryRecordsHandler(_context);
// when
bool result = await commandHandler.HandleAsync(command);
// then
Assert.IsTrue(result);
Assert.AreEqual(expectedInDatabase, _context.EmployeeWorkingTypeHistory.Count());
//Assert.IsFalse(_context.EmployeeWorkingTypeHistory.Any(ewth => historyToDelete.Contains(ewth.Id)));
}
}
}
If I found out why it fails, I will fix whole test but now I am stuck.
#Update 1
I found a issue. When im creating dbContext in SetupBeforeEachTest, im setting up Created to 2000.01.01. There is everything ok, but when im going out from this to the first test, when i checking up a DB i always have current date, not provided in SetupBeforeEach (2021.12.27)
SaveChanges when creating record updating Created date, so if you want to change Created date to test in future, you need to create new record first, then save changes, update it and save changes again.
Try to call the SetupBeforeEachTest() method in your ShouldClearHistory() method.
Related
How to get Element ID in schedules with c# and revit API? similar to this video with Dynamo - https://youtu.be/U-tVoCYilxo - but with c# and revit api.
When I execute my code, the third column doesn't appear and I get only two columns with width and height.
(I don't know what to write more - StackOverflow doesn't let me to post my issue without writing more text...)
here is my try:
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nice3point.Revit.Toolkit.External;
using Ecoworx.Core.Elements;
namespace Ecoworx
{
[Transaction(TransactionMode.Manual)]
public class CreateScheduleCommandHandler : ExternalEventHandler
{
public override void Execute(UIApplication uiapp)
{
UIDocument uidoc = uiapp.ActiveUIDocument;
Application app = uiapp.Application;
Document doc = uidoc.Document;
CreateSchedule(uiapp);
}
public static void CreateSchedule(UIApplication uiapp)
{
UIDocument uidoc = uiapp.ActiveUIDocument;
Application app = uiapp.Application;
Document doc = uidoc.Document;
using (Transaction t = new Transaction(doc, "Create single-category"))
{
t.Start();
// Create schedule
ViewSchedule vs = ViewSchedule.CreateSchedule(doc, new ElementId(BuiltInCategory.OST_Windows));
ElementId someId = new ElementId(BuiltInCategory.OST_Windows);
BuiltInParameter bip = (BuiltInParameter)(someId.IntegerValue);
doc.Regenerate();
// Add fields to the schedule
AddRegularFieldToSchedule(vs, new ElementId(BuiltInParameter.CASEWORK_WIDTH));
AddRegularFieldToSchedule(vs, new ElementId(BuiltInParameter.CASEWORK_HEIGHT));
AddRegularFieldToSchedule(vs, new ElementId(bip));
t.Commit();
}
}
public static void AddRegularFieldToSchedule(ViewSchedule schedule, ElementId paramId)
{
ScheduleDefinition definition = schedule.Definition;
// Find a matching SchedulableField
SchedulableField schedulableField =
definition.GetSchedulableFields().FirstOrDefault(sf => sf.ParameterId == paramId);
if (schedulableField != null)
{
// Add the found field
definition.AddField(schedulableField);
}
}
}
}
It seems like you're trying to cast an ElementId to a BuiltInParameter and then back to an ElementId.
Doesn't passing the id directly solve the problem?
So like this:
ElementId someId = new ElementId(BuiltInCategory.OST_Windows);
doc.Regenerate();
// Add fields to the schedule
AddRegularFieldToSchedule(vs, new ElementId(BuiltInParameter.CASEWORK_WIDTH));
AddRegularFieldToSchedule(vs, new ElementId(BuiltInParameter.CASEWORK_HEIGHT));
AddRegularFieldToSchedule(vs, someId);
The issue is in the Element ID of the parameter that will host the Element ID Property.
You have to get the ElementId of the parameter and then pass it into your method that shows the field in the schedule.
So I have written a plugin to do some simple calculations and and update fields based upon certain conditions. The plugin compiles and doesn't cause any errors while profiling or create any instances where I can debug my code which is frustrating. Anyways without further ado here it is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BPT.PluginCommon.BaseClasses;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Xrm;
namespace Engage.Crm.Plugins
{
public class VoidPayment : BPTPluginBase
{
bpt_DuesHeader oDuesHeader = new bpt_DuesHeader();
Account org = new Account();
public override void HandleAfterOp()
{
try
{
base.HandleAfterOp();
var crmContext = new XrmServiceContext(this.OrganizationService);
if (this.PluginExecutionContext.MessageName == MessageName.Create ||
this.PluginExecutionContext.MessageName == MessageName.Update)
{
if (this.InputTargetEntity.Attributes.Contains("gih_void"))
{
var Void = (bool) this.InputTargetEntity.Attributes["gih_void"];
var voidReason = (OptionSetValue) this.InputTargetEntity.Attributes["gih_voidreason"];
var totalPayments = (Money) this.InputTargetEntity.Attributes["bpt_TotalPayments"];
var amountBilled =
crmContext.bpt_DuesHeaderSet.Where(
o => o.bpt_DuesHeaderId == this.PluginExecutionContext.PrimaryEntityId)
.ToList()
.Sum(o => o.bpt_TotalAmountBilled == null ? 0 : o.bpt_TotalAmountBilled.Value);
if (Void)
{
this.oDuesHeader.bpt_TotalAdjustments = new Money(amountBilled);
this.oDuesHeader.bpt_TotalAmountBilled =
new Money(oDuesHeader.bpt_TotalAdjustments.Value + totalPayments.Value);
this.oDuesHeader.bpt_Balance = new Money(amountBilled);
if (voidReason.Value == 914020000)
//should be dropped not default option
{
oDuesHeader.gih_terminationdate = DateTime.Now;
}
}
OrganizationService.Update(oDuesHeader);
}
}
}
catch (Exception ex)
{
this.TracingService.Trace(this.ToString() + " {0}", "Exception: {0}", ex.ToString());
throw;
}
}
}
}
Sorry code is not formating well! Help! The plugin is registered as post-operation and synchronous. Any insight would be helpful and if a moderator could help format the code that would be greatly appreciated because it is not letting me add four spaces in certain places.
Plugins in CRM are created once, and then used multiple time, maybe even simultaneously, so besides setting the Id, don't use class level fields. You're creating a race condition that could really do some unwanted changes.
I'm playing with Entity Framework, and I have a Unit Test project that I want to exercise what I've done so far. I'd like to have it not actually update my test database when it's done. If I was working in SQL I would create a transaction and then roll it back at the end.
How can I do the same thing here?
As I understand it, context.SaveChanges(); is effectively doing the write to the database. And if I don't have that, then allCartTypes is empty after I assign it context.CarTypes.ToList()
Here's an example of one of my Test classes.
using System;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Trains;
using System.Linq;
namespace TrainsTest
{
[TestClass]
public class TestCarType : TestBase
{
[TestMethod]
public void TestCarTypeCreate_Success()
{
var tankerCarType = new CarType {Name = "Tanker"};
var boxCarType = new CarType { Name = "Box" };
using (var context = new TrainEntities())
{
context.CarTypes.Add(tankerCarType);
context.CarTypes.Add(boxCarType);
context.SaveChanges();
var allCartTypes = context.CarTypes.ToList();
foreach (var cartType in allCartTypes)
{
Debug.WriteLine(cartType.CarTypeId + " - " + cartType.Name);
}
}
}
}
}
I know I'm missing something fundamental, but I don't know what it is. and my googling has been fruitless.
There's a MSDN article about ef transactions.
http://msdn.microsoft.com/en-gb/library/vstudio/bb738523(v=vs.100).aspx
I am using C# and the Entity Framework to access a MySQL database.
I am grabbing the results of a stored procedure, and trying to turn them into a list of objects, However whenever it comes to the part what references a table through a one to many relationship, it fails with the error
There is already an open DataReader associated with this Connection which must be closed first.
The code I am using is here:
using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CarHireCommon.DataObjects;
namespace CarHireServer
{
public class DatabaseHandler
{
protected static DatabaseHandler instance;
protected carhireEntities1 Entities;
public static DatabaseHandler GetInstance()
{
if (instance == null)
instance = new DatabaseHandler();
return instance;
}
public DatabaseHandler()
{
Entities = new carhireEntities1();
}
public List<AvailableAssets> GetAvailableAssets(DateTime startDate, DateTime endDate)
{
ObjectResult<asset> res = Entities.GetAvailableAssets(startDate, endDate);
List<AvailableAssets> list = new List<AvailableAssets>();
foreach(var assetRes in res)
{
AvailableAssets asset=new AvailableAssets();
asset.id = assetRes.id;
asset.Comment = assetRes.comments;
asset.Make = assetRes.make;
asset.Model = assetRes.model;
asset.Fuel = assetRes.fuel;
asset.LongTerm = assetRes.longterm;
// This is the line that errors:
asset.Category = assetRes.category.categoryname;
list.Add(asset);
}
return list;
}
}
}
I have allready told it which table the Stored Procedure returns, and the other variables access correctly.
I have also tried doing it the long way with:
var cat = from b in Entities.categories where b.id == assetRes.category_id select b;
asset.Category = cat.FirstOrDefault<category>().categoryname;
However the thing still exceptions with the exact same error.
I found C# Entity Framework: There is already an open DataReader associated with this Connection which must be closed first which will probably help you exactly with this question.
GL!
I'm testing the MbUnit Framework and want to keep my test database in a persistent state after each test. How can I accomplish this?
This is what I'm trying, but my table is filled after the test is completed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using Gallio.Framework;
using MbUnit.Framework;
using NHibernate;
using NHibernate.Cfg;
namespace BusinessLayer.Tests
{
[TestFixture]
public class PersonNHibernateTests
{
[Test]
[Rollback]
public void CanSavePerson()
{
Configuration config = new Configuration();
config.Configure();
ISessionFactory factory = config.BuildSessionFactory();
using (ISession session = factory.OpenSession())
{
using (ITransaction tx = session.BeginTransaction())
{
const string CONST_STR_FIRSTNAME = "Stephen";
const string CONST_STR_LASTNAME = "Manga";
DateTime birthdate = new DateTime(1974, 6, 20);
Person p = new Person
{
FirstName = CONST_STR_FIRSTNAME,
LastName = CONST_STR_LASTNAME,
Birthdate = birthdate
};
session.SaveOrUpdate(p);
session.Flush();
tx.Commit();
}
}
}
}
}
Edit:
After some reading I've come to the understanding that Distributed Transaction Coordinator has to be enabled. After starting this service and testing still no success :(
You have a COMMIT statement in your code. Perhaps you should remove that.
I use Proteus it does just fine. Easy to setup and use..
All you need is to add some code to Setups TearDowns and prepare folder with 'snapshot' of your database.
Why not just let System.Transactions.TransactionScope handle it?
using (new TransactionScope())
{
// do stuff that gets automatically rolled back
}
Alternatively, this seems to be exactly what the MbUnit Rollback2 attribute does anyway (Rollback uses EnterpriseServices/COM+ and is aimed at .NET 1.1).