How to define the Context for a ModelSetup - moryx

The Documentation of the Moryx-Plattform provides an example for a hardcoded model setup in here, which I copied below
[ModelSetup(typeof(EmployeeContext))]
public class HardCodedSetup : IModelSetup
{
public int SortOrder => 1;
public string Name => "Sample";
public string Description => "Sample Description";
public string SupportedFileRegex => string.Empty;
[...]
}
My question now is, how the EmployeeContext would look like in this example?

EmployeeContext referes to an EntityFramework DbContext, so a database model. If you want to write a setup for products, target ProductsContext from Moryx.Products.Model.

Related

Serialization attributes on TableEntity in Azure Table Storage

Im using web API to return data in azure table storage. Im returning a class that I 'm inheriting TableEntity in a class and adding properties but want to keep to the .Net convention of capitalized property names but also keep to the JavaScript/json convention of lowercase properties names.
I've tried adding the Json.net property attributes to the class but it appears to be ignored. E.g.:
[JsonProperty("id")]
public string ID {get;set;}
If the instance has a value set on ID, null is represent in the serialized result.
According to your description, I tested this issue on my side and found it works well on my side and Azure. Here is my detailed steps, you could refer to it.
Create a controller named UserInfoController in the Web API application with the Get function like this:
// GET: api/UserInfo
[HttpGet]
public async Task<string> Get()
{
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(<your-Storage-ConnectionString>);
CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
CloudTable cloudTable = tableClient.GetTableReference("UserInfo");
TableQuery<User> query = new TableQuery<User>()
.Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "Grade Four"));
var results =await cloudTable.ExecuteQuerySegmentedAsync(query, null);
//Serialize the object to string by using the latest stable version of Newtonsoft.Json
string jsonString = JsonConvert.SerializeObject(results);
return jsonString;
}
Entity
public class User : TableEntity
{
public User(string partitionKey, string rowKey)
{
this.PartitionKey = partitionKey;
this.RowKey = rowKey;
}
public User() { }
[JsonProperty("id")]
public long ID { get; set; }
[JsonProperty("username")]
public string UserName { get; set; }
[JsonProperty("phone")]
public string Phone { get; set; }
[JsonProperty("age")]
public int Age { get; set; }
}
Result
Deploy the Web API application to Azure, then you could find the following result by calling the function via Fiddler.
In summary, please try to check the version of Json.NET you are using. If you aren't using the latest (9.0.1), then please try to upgrade to the latest version and run your application again to find whether it could work as expected.
FYI - while this doesn't answer the direct answer of how to get TableEntity to respect JSON.net attributes... I was able to solve the use case by overriding the ReadEntity and WriteEntity method in the inherited class:
e.g.
public class User : TableEntity{
//Upper case name
public string Name {get; set};
public override void ReadEntity(IDictionary<string, AzureTableStorage.EntityProperty> properties, OperationContext operationContext){
base.ReadEntity(properties, operationContext);
//lower case
this.Name = properties["name"];
}

Configure AutoMapper to return Mock in test layer

In my app, all domain classes follow the standardization:
All implement the interface IEntity
Id properties are protected*
The properties of type IList are protected and initialized in the constructor.
Below is a classic example of a domain entity:
public class CheckListItemTemplate : IEntity
{
public virtual int Id { get; protected set; }
public virtual string Text { get; set; }
public virtual CheckListItemTemplate Parent { get; set; }
public virtual IList<CheckListItemTemplate> Itens { get; protected set; }
public CheckListItemTemplate()
{
Itens = new List<CheckListItemTemplate>();
}
public void AddItem(CheckListItemTemplate item)
{
item.Parent = this;
Itens.Add(item);
}
}
*This is because the id is generated by the database and not run the risk of some developer trying to set this property.
Test project
We have a fake generic repository used in the tests:
public class Repository<T> : IRepository<T>
where T : class, IEntity
{
private readonly IDictionary<int, T> _context = new Dictionary<int, T>();
public void Delete(T obj)
{
_context.Remove(obj.Id);
}
public void Store(T obj)
{
if (obj.Id > 0)
_context[obj.Id] = obj;
else
{
var generateId = _context.Values.Any() ? _context.Values.Max(p => p.Id) + 1 : 1;
var stub = Mock.Get<T>(obj);
stub.Setup(s => s.Id).Returns(generateId);
_context.Add(generateId, stub.Object);
}
}
// ..
}
As you can see in the Store*, all test objects (of type IEntity) should be a Mock**. This is because in UI project, when we save an object NHibernate updating the property Id. In testing project we have to do this manually, and we have no way to set the property Id with a new value, so the solution was mock the entire object to the Get property Id correspond to the new Id . Exactly what does this line stub.Setup(s => s.Id).Returns(generateId).
*By convention, objects with Id <= 0 are new and Id> 0 are existing objects in the database.
**For Mock I use Moq.
Id as protected
The biggest problem occurs because of Id property and the fact that is protected.
When we talk about the designer, is a great approach but this brings huge inconvenience when we test our application.
For example, in a test that I'm writing I need my Fake repository with some data already populated.
Code
Follow me. I have the following classes (+ CheckListItemTemplate shown above.)
public class Passo : IEntity
{
public int Id { get; protected set; }
public virtual IList<CheckListItemTemplate> CheckListItens { get; protected set; }
}
public class Processo : IEntity
{
public virtual int Id { get; protected set; }
public virtual Passo Passo { get; set; }
public virtual IList<CheckListItem> CheckListItens { get; protected set; }
}
After saving the Processo, the first Passo is associated with the Processo: (sorted by Ordem field following field CreateAt)
model.Passo = PassoRepositorio.All().OrderBy(p => p.Ordem).ThenBy(p => p.CreateAt).First();
model.CheckListItens.Clear();
Parallel.ForEach(Mapper.Map<IList<CheckListItem>>(model.Passo.CheckListItens), (it) => model.AddCheckListItem(it));
This code is running whenever you save a new Processo. For any test that creates a new Processo, this code will be executed!
Test
If we have to create a test that creates a new Processo, our first goal is to populate the PassoRepositorio repository with some dummy data*, with Passos and CheckListItemTemplates specifically for the above code does not fail**.
*To populate objects with dummy data I use AutoFixture.
** Will fail if no Passo is found in the repository .First() and this Passo has no checklist Mapper.Map(model.Passo.CheckListItens).
So we need a repository of Passos and each Passo with a list of CheckListItens.
Remember that every object IEntity should be an Mock<> so we can mock property Id
First attempt
First configure my TestInitialize to populate my repository with some dummy data:
var fix = new Fixture();
var listPassos = fix.Build<Mock<Passo>>()
.Do((passo) => {
passo.SetupProperty(x => x.Nome, fix.Create<string>());
passo.SetupGet(x => x.CheckListItens).Returns(
fix.Build<CheckListItemTemplate>() // Needs to a Mock<>
.With(p => p.Texto)
.OmitAutoProperties()
.CreateMany(5).ToList()
);
})
.OmitAutoProperties()
.CreateMany(10);
foreach (var item in listPassos)
passoRepository.Store(item.Object);
Then I can run the tests:
[TestMethod]
public void Salvar_novo_processo_modificar_data_atendimento_passo_atual()
{
// Arrange
var fix = new Fixture();
var vm = fix.Create<ProcessoViewModel>();
//Act
Controller.salvar(vm); // Problem here. (For convert ProcessoViewModel to Processo I use a AutoMaper. In repository needs destination to be a Mock<Processo>
var processo = Repository.Get(p => p.DataEntrada == vm.DataEntrada && p.ProximoAtendimento == vm.ProximoAtendimento);
//Asserts
processo.Should().NotBeNull();
processo.Passo.Should().NotBeNull();
}
Questions
We create a list of 10 Passo where each Passo is actually is a Mock<>, great! But:
For each Passo have a list of 5 'Mock' items, and each Id should be 1, 2, 3, 4 and 5 (in that order). How to achieve this? How to obtain this list of IList<Mock<>> inside a Mock<> with Id already filled? That is, the configuration
passo.SetupGet(x => x.CheckListItens).Returns( ???
The responsible for creating objects in my controller, basically uses AutoMapper to convert my ViewModel object to an object that can be persisted Model in my repository:
model = Mapper.Map<TModel>(vm);
The problem is that my repository Fake can not save an object IEntity, just Mock<IEntity>. How to configure AutoMapper to always return a Mock<>?
Answer for Question 1: In case this helps, you can use a closure to maintain a running counter to use as an id. For example:
class MyTestClass
{
int _runningCounter = 0;
public void SomeTest()
{
/* ... some other code including mock creation ...*/
someMock.Setup(m => m.ReturnNewWidgetEntity())
.Returns(() => new WidgetEntity{ Id= ++_runningCounter });
}
}
Each time ReturnNewWidgetEntity is called on the mocked object, the Id property will be set to an increased number.
Answer for Question 2: I would suggest that rather than having a concrete dependency on the Mapper class, you replace this with an injected dependency on IMapperEngine. Richard Dingwall explains the technique here: http://richarddingwall.name/2009/05/07/mocking-out-automapper-with-dependency-injection/
Basically you register Mapper.Engine as the singleton implementation of IMapperEngine in your container and then in your unit tests mock it so that it gives you the required Mock<> classes.
I hope one or both of these answers at least give you food for thought. It was a bit difficult to follow your whole example, to be honest!

NHibernate 3 Linq and IUserType

I have a table:
Page (
Id int,
Name nvarchar(50),
TemplateName varchar(50)
...
)
and it's mapped to domain model:
public class Page {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Template Template { get; set; }
}
Note that in the domain model, "Template" property is not of type "string".
The Template class is like this:
public class Template {
public string Name { get; set; }
// other properties...
}
"Templates" are loaded from file system. I have a TemplateManager class:
public class TemplateManager {
public static Template LoadTemplate(string templateName) {
// check if there's a folder named <templateName>
}
}
I can use IUserType to map the "Template" property.
public class PageMap : ClassMapping<Page> {
public PageMap() {
...
Property(c => c.Template, m => {
m.Column("TemplateName");
m.Type<TemplateUserType>();
}
}
}
public class TemplateUserType : IUserType {
public object NullSafeGet(System.Data.IDataReader rs, string[] names, object owner)
{
var templateName = rs[names[0]].AsString();
if (!String.IsNullOrEmpty(templateName))
{
return TemplateManager.LoadTemplate(templateName);
}
return null;
}
}
Okay, so far so good. But the problem is, how can I use Template property in Linq queries?
For exmaple:
var pages = session.Query<Page>().Where(it => it.Template.Name == "MyTemplate");
I think the solution might be to write a class (say TemplatePropertyHqlGenerator) implementing IHqlGeneratorForProperty. This is the linq query extension point provided by NHibernate 3. But how to write this TemplatePropertyHqlGenerator class?
Thanks in advanced!
The IUserType interface lets you define a type which is considered atomic. That is to say, you can then perform direct comparisons between instances of the type and NHibernate will know how to translate them.
E.g. the following query would evaluate:
var template = new Template();
session.Query<Page>().Where(it => it.Template == template);
If you want to define a type which has component values which you can then manipulate, you need to implement the ICompositeUserType interface. This interface requires you define the properties of the type as atomic elements, giving NHibernate the information it needs to understand the specific properties of the type.
As a result, it's a little more complex than IUserType to implement, but it should facilitate what you want to achieve.
Here's an understandable example of implementing the interface for a Money type: http://geekswithblogs.net/opiesblog/archive/2006/08/05/87218.aspx

View and Domain model, where to perform calculation

I just started using View & Domain model design in my MVC web app but got the question where to perform calculations and other View related actions. I will try to give example below.
My Domain Model (Linq2Sql)
public class Product
{
public int Id;
public string Name;
}
The View Model with new UserCount property which I would like to calculate.
public class ProductViewModel
{
public int Id;
public string Name;
public int UserCount;
}
My controller action looks like
public ActionResult _SelectionClientSide_Products()
{
IQueryable<Product> products = _repository.GetProducts(true);
var model = Mapper.Map<IEnumerable<Product>, IEnumerable<ProductViewModel>>(products);
return View(model);
}
I query for data using repository method and get IQueryable<Product> and map it to ProductViewModel list. But I also need to perform another query operation to count users for every queried product and assign all values to ProductViewModel. What design I should follow to achieve this?
The relationship between tables
Products -> Orders - > Users
EDIT
I have decided to remove AutoMapper because it gives more problems than benefits and created my own Builder which contain everything what I need. I make field assign and also add calculation.
public ActionResult _SelectionClientSide_Products()
{
Data = new ProductViewModelBuilder(_repository).Build();
return View(Data);
}
namespace PC.Models
{
public class ProductViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int UsersCount { get; set; }
}
public class ProductViewModelBuilder
{
private readonly IDataAccess _repository;
public ProductViewModelBuilder(IDataAccess repository)
{
_repository = repository;
}
public IQueryable<ProductViewModel> Build()
{
return _repository.GetProducts().Select(p=> new ProductViewModel
{
Id = p.Id,
Name = p.Name,
UsersCount = _repository.CountUsers(p.Id)
});
}
}
}
In my opinion, by the time your Controller has begun it's model setup, there should be no more "logic" or talking to the model. Having a "builder" which queries the model again is bad practice. Not really "breaking" the MVC pattern, but still bad practice. Your ViewModel has a dependency on your DAL. Bad bad boy. :)
If you have to run another query, well that should be encapsulated in the original query. Instead of calling _repository.GetProducts, call a different method which not only gets the products, but get's the count as well. Create a DTO if necessary.
Then your controller should look like:
public ActionResult _SelectionClientSide_Products()
{
var someDto = _repository.GetProductsAndUserCount(true);
var model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);
return View(model);
}
Personally i go for generic repositories over specialized ones, as i don't want a IProductRepository interface with 50 signatures. I opt for LINQ IEnumerable<T> extensions (aka "pipes and filters") which allows complex queries to be built and remain in my domain.
So my version of the above would be:
public ActionResult _SelectionClientSide_Products()
{
var someDto = _productRepository.Find().WithSomeCondition(true).ToSomeDto();
var model = Mapper.Map<IEnumerable<SomeDto>, IEnumerable<ProductViewModel>>(someDto);
return View(model);
}
On a side note, why do you say AutoMapper causes you more problems that benefits? AutoMapper has saved me tons and tons of repetitive code. If you know how to use it properly, it's your best friend. Hands down the most important NuGet package in my current application.

MetaData class for entityframework POCO

I am creating a meta data class for a POCO object. I am adding the "CSVColumn" (from LINQToCSV) attribute to the meta data class. But when I run the program, it couldn't find its attributes.
So I tested it using reflection,
Type t = typeof(Case);
PropertyInfo pi = t.GetProperty("ProviderId");
//bool isReadOnly = ReadOnlyAttribute.IsDefined(pi,typeof( ReadOnlyAttribute);
var attributes = pi.GetCustomAttributes(typeof(Case),true);
It acutally return nothing by calling the "GetCustomAttributes".
What have I done wrong??
Below is the way I created metadata class.
One thing I don't understand is, it works perfectly well with MVC validations. Wondering how does that retrieve the custom attributes???
This is the entityframework POCO object
public partial class Case
{
public string ProviderName { get; set; }
public string ProviderId { get; set; }
}
Here I create a partial class of Case and metadata classes,
[MetadataType(typeof(CaseMetaData))]
public partial class Case
{
public class CaseMetaData
{
[CsvColumn(Name = "ProviderName", FieldIndex = 1)]
public string ProviderName { get; set; }
[CsvColumn(Name = "ProviderID", FieldIndex = 2)]
public string ProviderId { get; set; }
}
}
Please someone can help me, much appreciated.
Cheers
typeof(Case) isn't an attribute type.
You mean typeof(CsvColumnAttribute).
Also, standard Reflection isn't aware of metadata classes.
You need to use AssociatedMetadataTypeTypeDescriptionProvider.
A good example can be found here

Resources