How to avoid code duplication in MVVM? - silverlight

This question is similar to Where does business logic sit in MVVM?
However, I didn't want to create a comment chain on that one
Lets say for example that I have a table of invoices and I want to get this data and perform some apportionment on it ready for use in 2 totally separate reports and 3 screens.
In our current web application I would have put this in the Data Service Layer, and all of my reports and screens would have called this
In MVVM people seem to suggest that the model should not be bloated out and that logic should be put in the view models. But in this case I be duplicating the code 5 times?
In his answer to my other question Reed states "Anything that's specific to the domain or business should be reusable by other applications, using other architectures."
Can Reed or someone clarify what my approach should be? Can MVVM be combined with other architectures?
I am using Silverlight 5 with the Simple MVVM Toolkit
Paul

The ViewModel is not for business logic. It is for user interface logic. As its name is given, it is representing the View. If you have five different reports that presents similar data, give this data a name and make all five ViewModels understand how to work with the data objects.
Since we are talking about reports, data is understood to e only displayed. The ViewModel can just be a simple data source with minimal user interface interaction, basically a very thin layer.

I faced the same problem and decided to go this way:
I created classes like controllers in MVC (performing some actions with my model) and I work with them in all ViewModels.
For example: our application has a list of books. We need to add/edit/delete them.
So we have a model:
public class Book {
public int BookId { get; set; }
public string Title { get; set; }
public string Author { get; set; }
}
Then we have a controller class:
public class BookController {
string dbPath = ...;
public void AddBook(string title, string author)
{
var book = new Book() { Title = title, Author = author };
AddBook(book);
}
public void DeleteBook(int id)
{
using (var db = new SQLiteConnection(dbPath))
{
db.Delete<Book>(id);
}
}
public void DeleteBook(Book book)
{
using (var db = new SQLiteConnection(dbPath))
{
DeleteBook(book.BookId);
}
}
public List<Book> GetAllBooks()
{
using (var db = new SQLiteConnection(dbPath))
{
return db.Table<Book>().ToList();
}
}
public Book FindBook(string title, string author, int id)
{
.....
}
}
Now we can use it wherever we need, e.g.:
public class BookListViewModel : ViewModelBase {
public BookListViewModel() {
GetData();
}
void GetData()
{
BookController bc = new BookController(); // here we start using our controller.
_books = new List<Book>();
_books = bc.GetAllBooks();
}
}
Such approach helps us:
1) keep all business logic separately (in controller class)
2) avoid code duplication

Related

how to create an object using another as a source in Autofixture?

I have something like this:
public class ModelEntity : Entity
{
public override int Id { get; set; }
public string FileName { get; set; }
}
public class DataTransferObject
{
public int Id { get; set; }
public string FileName { get; set; }
}
And I would like to do something like this:
var model = _fixture.Create<ModelEntity>();
var dto = _fixture.Create<DataTransferObject>().FillWith(model);
Right now I am doing the following but I am not sure if is the right way to do it
var model = _fixture.Create<ModelEntity>();
var dto = model.AsSource().OfLikeness<DataTransferObject>().CreateProxy();
AutoFixture doesn't have a feature like that, but I think there's something better to be learned from this:
AutoFixture was originally built as a tool for Test-Driven Development (TDD), and TDD is all about feedback. In the spirit of GOOS, you should listen to your tests. If the tests are hard to write, you should consider your API design. AutoFixture tends to amplify that sort of feedback, and it may also be the case here.
It sounds like you need to be able to populate a DataTransferObject with values from a ModelEntity instance. Could this suggest that some sort of mapping would be a valuable addition to your API?
Depending on how these types are already coupled, you could consider adding a projection method to your ModelEntity class:
public class ModelEntity : Entity
{
public override int Id { get; set; }
public string FileName { get; set; }
public DataTransferObject ToDataTransferObject()
{
return new DataTransferObject
{
Id = this.Id,
FileName = this.FileName
};
}
}
However, the disadvantage of this approach is that it couples those two types to each other.
If you find that undesirable, you could instead introduce a dedicated Mapper Service, which can map a ModelEntity instance to a DataTransferObject object - and perhaps vice versa.
If, for some unfathomable reason, you don't want to introduce such a Mapper into your System Under Test, you can still add it as a reusable Service in your test project.
If you don't wish to write such a Mapper yourself, you could consider using something like AutoMapper for that purpose.

dreaded "Ids can not be autogenerated for entities with multipart keys"

Ok I’m at a loss, being new to breeze I’m still learning the ropes. My project uses the hot towel template for AngularJs and breeze from John Papa.
He's what I’m trying to achieve: I have a master\slave tables in my database. An "Agency" has many people it can "Notify". Here are the EF classes for the server side:
public class Agency {
public Agency() {
this.Notifies = new HashSet<Notify>();
}
public long Id { get; set; }
[Required, MaxLength(50)]
public string Name { get; set; }
<<removed unneeded details>>
public bool Active { get; set; }
public virtual ICollection<Notify> Notifies { get; set; }
}
public class Notify
{
public long Id { get; set; }
public long? AgencyId { get; set; }
public string Name { get; set; }
<<removed unneeded details>>
public virtual Agency Agency { get; set; }
}
Now the Maps:
public class AgencyMaps : EntityTypeConfiguration<Agency>
{
internal AgencyMaps()
{
HasKey(x => x.Id);
}
}
public class NotifyMap : EntityTypeConfiguration<Notify>
{
internal NotifyMap()
{
HasKey(x => x.Id);
HasOptional(x => x.Agency)
.WithMany(p => p.Notifies)
.HasForeignKey(i => i.AgencyId);
}
}
Now on the client side I use breeze to create new entities like this:
// create a new entity
function create() {
return manager.createEntity(entityName);
}
// create a new notify entity
function createNotify(){
return manager.createEntity(entityNameNotify);
}
Then there are two scenarios I need to achieve:
- First is where I retrieve an existing agency and add additional
people to notify
- Second is where I create a new agency and add people
to notify
Both fail in the same place.
Note: I’m using SQL server and my Id fields are bigint (long) at this point in time.
I’m retrieving the “Agency” entity and placing it in a variable called “vm.agency”. “vm.agency” has a navigation called “notifies” with an entity type of “Notify”. So when I want to create and add a new person I’m calling this function:
function addNotifyRec(){
if (vm.agency !== undefined){
var notifyRec = datacontext.agency.createNotify(); //<<< fails here
notifyRec.agencyId = vm.agency.id;
notifyRec.name = vm.notify.name;
<<removed unneeded details>>
vm.agency.notifies.push(notifyRec);
logSuccess(“New person to notify added”);
}
else
{ logError(“Agency is undefined”); }
}
As soon as the createNotify() is called I get the “Ids can not be autogenerated for entities with multipart keys” error.
So I’m stuck. It seems to me this is a pretty common scenario. I am obviously not understanding the breeze framework well enough to implement this. If you can point me in the right directions I’d appreciate your help.
UPDATE 4/9/2014
I'm thinking i could eliminate this issue altogether if i switch over to guid id and generate them client side. Is this correct thinking?
What's interesting here is that Breeze thinks that Notify.Id and Notify.AgencyId are multi part primary keys but they are actually not. Id is a PK and AgencyId is an FK. The only thing that I can think of is try removing the EntityTypeConfiguration for both Agency and Notify, specifically the part where it specifies HasKey and HasForeignKey. This Fluent API configuration shouldn't be required as EF will match your configuration by convention instead.
I took a different approach on working around my issue. Since i have the luxury to change out the id types, i swapped out the bigint ids to Uuid types and removed the auto generation of the ids in sql. Now i'm just creating my own ids using breeze.core.getUuid() when a new record is created. Not sure this is the most efficient way to work around the issue, but it seems to be working fine.

breezejs createEntity is undefined

Inside an AngularJS directive, I assign a new value to a scope variable:
$scope.myPerson = { TiersId: 105191, Name: "John Smith" };
Originaly the $scope.myPerson was created from a BreezeJS entity.
Assigning the new value triggers a $scope.apply() by AngularJS, which is then intercepted by BreezeJS. That's when it gets complicated.
[EDIT]
Ok, I've figured out that I need to use the EntityManager that I've registered with my dataContext:
$scope.myPerson = myDataContext.createPerson({ TiersId: 105191, Name: "John Smith" });
function createPerson(person) {
return manager.createEntity("AccountOwner", person);
}
Now, it fails in the following code:
proto.createEntity = function (typeName, initialValues, entityState) {
entityState = entityState || EntityState.Added;
var entity = this.metadataStore
._getEntityType(typeName)
.createEntity(initialValues);
if (entityState !== EntityState.Detached) {
this.attachEntity(entity, entityState);
}
return entity;
};
The entity type is known, but the createEntity(initialValues) function is undefined. How come ?
[EDIT]
To make things clearer, here's the relevant EF mapping as well as the model classes:
public class MandateMappings : EntityTypeConfiguration<Mandate>
{
public MandateMappings()
{
Property(m => m.IBAN).HasMaxLength(34).IsFixedLength().IsUnicode(false);
Property(m => m.AccountOwner.Name).HasMaxLength(70);
Property(m => m.AccountOwner.City).HasMaxLength(500);
Property(m => m.CreatedBy).HasMaxLength(30);
Property(m => m.UpdatedBy).HasMaxLength(30);
}
}
public class Mandate : Audit
{
public string IBAN { get; set; }
public AccountOwner AccountOwner { get; set; }
}
public class AccountOwner
{
public string Name { get; set; }
public string City { get; set; }
}
public abstract class Audit
{
public DateTime CreatedDate { get; set; }
public string CreatedBy { get; set; }
}
Let me clarify what I meant when I said on User Voice that Breeze supports a form of inheritance but not "database inheritance".
I meant that, today, the classes on your server-side can be part of an inheritance chain if and only if that chain is invisible to the client.
Here are some conditions consistent with that caveat:
Only the "terminal" class in the chain (the most derived class) maps to a database table.
Properties on super classes are non-public (e.g., internal) or explicitly not mapped (e.g., adorned with [System.ComponentModel.DataAnnotations.Schema.NotMapped].
Methods may appear on any class at any level as these are never transmitted to the client.
Here is an example of a TodoItem class that inherits from a baseClass:
public class baseClass
{
public void DoNothing() {}
internal string Foo { get; set; }
}
public class TodoItem :baseClass
{
public int Id { get; set; }
[Required, StringLength(maximumLength: 30)]
public string Description { get; set; }
public System.DateTime CreatedAt { get; set; }
public bool IsDone { get; set; }
public bool IsArchived { get; set; }
}
This works fine on the server. Set a breakpoint in the controller: you'll have no trouble executing DoNothing() and getting/setting the Foo property.
This works because there is no client-side consequence of this structure. The metadata are no different after deriving from baseClass than they were before. The Foo property and DoNothing methods are invisible to the client … exactly as this service author intended.
This kind of arrangement is pretty common in the real world where the many classes of a business model share functionality through a base class.
This is NOT the end of the story and it is NOT what we think people are asking for when they ask for "inheritance".
We think people want what I have been calling "database inheritance" by which I mean that two or more classes in the inheritance chain are mapped to different tables.
Breeze does not handle that today ... in part because Breeze cannot yet comprehend metadata that describe an inheritance hierarchy.
Workaround
What if you had a class hierarchy in which data properties were defined on different class levels? You can workaround the current obstacles by providing a metadata description that flattens the hierarchy from the perspective of the client.
For example, suppose you have a Person type with FirstName and LastName. And Person derives from entityBase which defines createdBy.
If you define the Person *EntityType* to have [FirstName, LastName, and createdBy] properties - essentially flattening the hierarchy - all will be well.
Flatten the hierarchy automagically
Of course that's a PITA. One approach to inheritance we could take is to do this flattening for you when you ask Breeze to generate the metadata on the server.
I'm curious: would this suffice? Or do you really NEED to know on the JavaScript client that the createdBy property belongs to a base class. If you really need to know, please tell me why.
Edit: As of v 1.3.1 Breeze now DOES support inheritance.
Without more context I can't be sure, but I'm guessing that the issue is that Breeze does not YET have metadata about your entityType. Normally this is accomplished via your first query, but if you are creating entities before the first query then the alternative is to call the EntityManager.fetchMetadata() method instead BEFORE performing any createEntity calls. The fetchMetadata method is asynchonous, i.e. returns a promise, so you will need to perform your createEntity call inside of the 'then' portion of the promise. There are a couple of other recent 'Breeze' posts similar to this that have more details and examples.

Initializing DTOs on the server-side when using RIA services

Say you have an domain entity with business logic for initializing its default values. E.g.
class User : IUser, Entity
{
public User()
{
StartDate = DateTime.Now;
EndDate = StartDate.AddDays(3); // This value could be user-configured.
}
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
Using RIA services, the DTO that will be generated of course does not include any logic, only public properties. Which means that when a client (e.g. Silverlight application) displays a 'create new user' dialog, it will not be able to populate the fields with any default values (without, of course, duplicating the business logic on the client).
In an attempt to achieve this, I created new DTO (UserDTO) and a query in my UserDomainService:
// Construct a new domain entity and then convert to DTO
public UserDTO CreateNewUser()
{
var user = new User(); // Business logic has now been executed.
return new UserDTO(user);
}
This does allow the client to populate fields with default values, however when it comes time to add the newly created user, RIA has already added the UserDTO to it's internally mainted collection of entities, so you cannot call .Add on your domain context. You can still just call SubmitChanges, which will trigger the [Update] method to be called, however this seems to be going against the grain of how RIA services is supposed to be used (i.e. you shouldn't be doing an INSERT operation in an UPDATE method).
Is this scenario (i.e. server-side creation of DTOs) achievable in RIA services?
I don't know what your business logic looks like, but if you used a common method to save objects (whether new or modified) on the server, than you would be able to differentiate within that method, whether it is a modified object or really a new one.
Example on the server:
[Insert]
public void InsertUser(UserDTO user)
{
this.SaveUser(user);
}
[Update]
public void UpdateUser(UserDTO user)
{
this.SaveUser(user);
}
You could add a property to your User (or the base class, if you have one):
public class UserDTO
{
[...]
// only set this within the constructor,
// unfortunately it cannot be "private set", because of RIA Services
public bool IsNewEntity { get; set; }
}
In your SaveUser method use that flag:
private void SaveUser(UserDTO user)
{
if (user.IsNewEntity)
{
// do something with a new user
}
else
{
// do something with an existing user
}
}
The Constructor for the UserDTO would then be:
public UserDTO()
{
this.IsNewEntity = true;
}
I know, this looks a little trivial, but I do not know of a more "elegant" way.

Winforms: access class properties throughout application

I know this must be an age-old, tired question, but I cant seem to find anything thru my trusty friend (aka Google).
I have a .net 3.5 c# winforms app, that presents a user with a login form on application startup. After a successful login, I want to run off to the DB, pull in some user-specific data and hold them (in properties) in a class called AppCurrentUser.cs, that can thereafer be accessed across all classes in the assembly - the purpose here being that I can fill some properties with a once-off data read, instead of making a call to the DB everytime I need to. In a web app, I would usually use Session variables, and I know that the concept of that does not exist in WinForms.
The class structure resembles the following:
public class AppCurrentUser {
public AppCurrentUser() { }
public Guid UserName { get; set; }
public List<string> Roles { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
}
Now, I have some options that I need some expert advice on:
Being a "dumb" class, I should make the properties non-static, instantiate the class and then set the properties...but then I will only be able to access that instance from within the class that it was created in, right?
Logically, I believe that these properties should be static as I will only be using the class once throughout the application (and not creating new instances of it), and it's property values will be "reset" on application close. (If I create an instance of it, I can dispose of it on application close)
How should I structure my class and how do I access its properties across all classes in my assembly? I really would appreciate your honest and valued advice on this!!
Thanks!
Use the singleton pattern here:
public class AppUser
{
private static _current = null;
public static AppUser Current
{
get { return = _current; }
}
public static void Init()
{
if (_current == null)
{
_current = new AppUser();
// Load everything from the DB.
// Name = Dd.GetName();
}
}
public string Name { get; private set; }
}
// App startup.
AppUser.Init();
// Now any form / class / whatever can simply do:
var name = AppUser.Current.Name;
Now the "static" things are thread-unsafe. I'll leave it as an exercise of the reader to figure out how to properly use the lock() syntax to make it thread-safe. You should also handle the case if the Current property is accessed before the call to Init.
It depends on how you setup your architecture. If you're doing all your business logic code inside the actual form (e.g. coupling it to the UI), then you probably want to pass user information in as a parameter when you make a form, then keep a reference to it from within that form. In other words, you'd be implementing a Singleton pattern.
You could also use Dependency Injection, so that every time you request the user object, the dependency injection framework (like StructureMap) will provide you with the right object. -- you could probably use it like a session variable since you'll be working in a stateful environment.
The correct place to store this type of information is in a custom implementation of IIdentity. Any information that you need to identify a user or his access rights can be stored in that object, which is then associated with the current thread and can be queried from the current thread whenever needed.
This principal is illustrated in Rocky Lhotka's CLSA books, or google winforms custom identity.
I'm not convinced this is the right way but you could do something like this (seems to be what you're asking for anyway):
public class Sessions
{
// Variables
private static string _Username;
// properties
public static string Username
{
get
{
return _Username;
}
set
{
_Username = value;
}
}
}
in case the c# is wrong...i'm a vb.net developer...
then you'd just use Sessions.USername etc etc

Resources