Repository pattern with simple select stored procedure - asp.net

I have implemented the repository pattern using the following generic interface.
public interface IRepository<T> where T : class
{
IQueryable<T> All { get; }
IQueryable<T> AllIncluding(params Expression<Func<T, object>>[] includeProperties);
T Find(int id);
void InsertOrUpdate(T updateObject);
void Delete(int id);
void Save();
}
I then create the individual repositories and call them from my service layer.
I have a table in my database that is populated with the last date that one of our data feeds runs (it will only ever contain one record). All I need to do is get this date from the database. What is a good way to do this? Surely creating a repository for this simple read only table is overkill? Should I create a function or stored proc in the database to return this date and if I do how would it fit in with the repository pattern?

You shouldn't inherit from the general IRepository<T> interface because most of those methods won't make any sense.
But since you already state that you could use a stored procedure, a LINQ query or maybe even esql it would still be a good idea to encapsulate the data retrieval. What if you want to change the mechanism or apply some caching?
Also think about unit testing, your code depends on this 'last date', so in your unit tests you want to be able to supply different dates. A mockable repository will be the easiest.
Maybe you can add the LastModificationDate as a function to your ObjectContext. Then you have on single point of access and in a FakeObjectContext you can return specific dates for testing purposes.

If you can use an abstract for the repository definition rather than an interface, you can add the date-code directly to the abstract and have it inherited by all your repositories.

Related

D365FO x++ syscomputedcolumn table name

How can you use the syscomputedcolumn class to retrieve a table or field name for an entity? this is fairly easy using virtual field entity postload method something like
public class SysDatabaseLogHeaderEntity extends common
{
public void postLoad()
{
super();
this.TableName = tableId2Name(this.table);
}
}
but there's a rumour that virtual fields won't be supported in upcoming synapse link for D 365 FnO so want to know how to do this with computed columns...
https://learn.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/data-entity-computed-columns-virtual-fields
SysComputedColumn is used to help create computed columns in views.
Supposing for some reason you want a column in which every row contains the string value "CustTable", you'd create create a method (AX 2012 syntax):
public static server string TableNameColumn()
{
return SysComputedColumn::returnLiteral(tableStr(CustTable));
}
and then you'd add a computed column to the view as outlined here: https://learn.microsoft.com/en-us/dynamicsax-2012/developer/walkthrough-add-a-computed-column-to-a-view
Note: hopefully this is a toy example, there is no reason to ever actually do this particular column. Or really any fully static columns.
View computed columns are essentially based on static server methods which return the SQL definition for the computed column, and then the SysComputedColumn class has a bunch of helper methods to let you build those SQL string statements without using specific implementation knowledge of the backend database such as column names.
A complete description is beyond the scope of this comment, but the big one you'll use is SysComputedColumn::returnField(view,datasource,field) which gets the specified field from the specified datasource in the specified view. You want to use intrinsic functions for these parameters to keep your cross references valid (https://learn.microsoft.com/en-us/dynamicsax-2012/developer/intrinsic-functions).
There will be a lot you can't do though. These are sql only so they cannot send individual rows into X++ business logic. You need to reconstruct said business logic in SQL which can't always be done easily.
I like to keep those methods public so I can info them out and test them in SQL directly. I'm guessing you can't access the sql in d365, but looking at the string returned from your method can still help in troubleshooting.

Linq Expressions on Repository Interface

I'm currently trying to find the right architecture for my Solution, but I have one doubt, is it wrong to create a Repository Interface containing methods with lambda expression arguments?
For example:
IEnumerable<TEntity> GetAll(Func<TEntity, bool> where);
Using Entity Framework i can easily implement this on my concrete repository:
public virtual IEnumerable<TEntity> GetAll(Func<TEntity, bool> where)
{
return DbSet.Where(where).ToList();
}
But our main objective by separating data access on another layer is to provide an abstraction on the data access and facilitate future data hosting migrations.
Is it possible to implement this repository method on another Data access technology? For example sql queries directly to database?
Yes, this is possible, but it is not very simple. What you need to do is to implement an IQueryable<T> LINQ Provider.
This walkthrough from Microsoft explains how to do it. You may need to change the signature of your method to take IExpression<Func<TEntity, bool>>, and returning IQueryable<TEntity>:
public virtual IQueryable<TEntity> GetAll(IExpression<Func<TEntity, bool>> where)
{
return DbSet.Where(where).ToList();
}

Where should Stored Proc business logic be placed in MVC?

I'm looking for a bit of experience and explanation here, given that different sources give different recommendations. I am totally new to MVC. I know this question has been asked before, but I am not (currently) using EF or Linq.
I have a SQL database with many stored procedures. Previously when used with webforms, there was a business layer that contained helper methods for calling the procedures and returning DataSets to the pages. The important part is that the procedures often interrogated about 20 tables; the pages do not simply reflect the database structure exactly (as I see in the majority of MVC tutorials):
SQL database <--> stored procedures <--> business layer <--> web forms
I want to take the best approach here to start on the right footing and learn properly but appreciate there may not be a correct answer. Therefore if you post, could you please offer some explanation as to "why"?
Should stored procedure logic (SQLCommand/business methods etc) go within Model or
Controller?
One post advises neither, but retain the business layer. Another expert advises that
[Models/Entities] should not have any addon methods outside of what's
coming back from the database
If the business layer is retained, where are the methods called from (e.g. Model or Controller)?
If the above answer is "Neither", does that mean the Model part will go unused?
That almost feels that things aren't being done properly, however in this tutorial that appears to be what happens.
Should I plug in the Entity Framework into the Model layer to call the business layer?
That feels like overkill, adding all that additional logic.
Your controllers should gather the information required to build the page the user is currently viewing. That's it.
Controllers should reference classes in your business logic layer.
For example here's your controller. All it does is translate the http request and call the business logic.
public class MyController : Controller
{
private IMyBusinessLogic _businessLogic;
public MyController(IMyBusinessLogic businessLogic)
{
_businessLogic = businessLogic;
}
[HttpPost]
public ActionResult UpdateAllRecords()
{
_businessLogic.UpdateAllRecords();
return Json(new Success());
}
}
And your business logic class
public class MyBusinessLogic : IMyBusinessLogic
{
public void UpdateAllRecords()
{
// call SP here
using(SqlConnection conn = new...
}
}
There are a number of advantages to this:
Your business logic is completely separated from your UI, there's no database code in your presentation layer. This means your controller can focus on it's job and code doesn't get polluted.
You can test your controller and see what happens when your business logic succeeds, throws exceptions etc.
For extra bonus points you should look into creating a data access layer.
public void DataAccess : IDataAccess
{
public void RunStoredProcedure(string spName)
{
}
}
Now you can test that your BLL is calling and processing your SP results correctly!
Expanded following the comment questioning the models:
Ideally your model should have no logic in it at all. It should simply represent the data required to build the page. Your object which you're loading represents the entity in the system, the model represents the data which is displayed on the page. This is often substantially lighter and may contain extra information (such as their address) which aren't present on the main entity but are displayed on the page.
For example
public class Person
{
public int PersonID {get;set;}
public string Firstname {get;set;}
public string Lastname {get;set;}
public Address Address {get;set;}
}
The model only contains the information you want to display:
public class PersonSummaryModel
{
public int PersonID {get;set;}
public string FullName {get;set;}
}
You then pass your model to your view to display it (perhaps in a list of FullNames in this case). Lots of people us a mapper class to convert between these two, some do it in the controller.
For example
public class PersonMapper
{
public PersonSummaryModel Map(Person person)
{
return new PersonSummaryModel
{
PersonID = person.PersonID,
FullName = string.Concat(person.Firstname, " ", person.Lastname)
};
}
}
You can also use some automatic solutions such at AutoMapper to do this step for you.
Your controller should really only be involved with orchestrating view construction. Create a separate class library, called "Data Access Layer" or something less generic, and create a class that handles calling your stored procs, creating objects from the results, etc. There are many opinions on how this should be handled, but perhaps the most
View
|
Controller
|
Business Logic
|
Data Access Layer
|--- SQL (Stored procs)
-Tables
-Views
-etc.
|--- Alternate data sources
-Web services
-Text/XML files
-and son on.
if you feel like learning tiers and best way
MSDN have great article on this link
MSDN

What are the some data access options for manipulating data using asp.net controls?

My first question on SO!
What I'm working on is a Webforms page that's has a lot ASP textboxes, datepickers and dropdowns. Right now I'm using ADO.net for all of these controls to do CRUD operations.
I'm already a great deal into this project, but I can't help wondering if I could be doing this in an easier or more efficient way. So far I'm using the SqlDataReader class for everything.
If someone could break down the different options available to me or point me to some good information, I'd appreciate it. I know it's a pretty broad topic. I'm kind of aware of LINQtoSQL and EntityFramework.
So my question really is: How does ADO.net compare to LINQtoSQL or EntityFramework?
you should read up on one sample each of ADO.NET, Linq 2 SQL and Entity Framework and implement them to know the pros/cons of each. a simple web search should give you samples.
Linq2Sql and EF will require very SQL query writing from you. once you have an initial grasp of these 3 things individually, follow this simple pattern in your code:
define an interface for your data access.
let your code behind (ascx.cs and aspx.cs) work with the interface.
define concrete implementations of the interface based on ADO.NET, Linq2Sql or EF.
e.g.
public interface IRepository
{
MyDto GetData(int id);
// and so on
}
public class EntityFrameworkRepository : IRepository
{
public MyDto GetData(int id)
{
using (var db = new MyDbContext())
{
var myDtoEntity = db.MyDtoEntity.FirstOrDefault(m => m.Id == id);
// extension method to transform DB objects into DTOs
return myDtoEntity.ToMyDto();
}
}
}
// similarly you can do:
public class Linq2SqlRepository : IRepository
{
// so on..
}
// now for all your aspx.cs pages: derive them from a base page,
// and in the base page
// have a variable like this, so that all pages have access to this.
public IRepository Repository {get; set;}
// you can have static instances as well for one time initialization.
// you can initialize the Repository with a particular concrete implementation
// or inject it. (if you're well versed with Dependency Injection)
using the above way, all your code will work off the Interface, and you just need to change one place if you decide to change the implementation.

Usage of repository between EF model and code consumer

I have binary data in my database that I'll have to convert to bitmap at some point. I was thinking whether or not it's appropriate to use a repository and do it there. My consumer, which is a presentation layer, will use this repository. For example:
// This is a class I created for modeling the item as is.
public class RealItem
{
public string Name { get; set; }
public Bitmap Image { get; set; }
}
public abstract class BaseRepository
{
//using Unity (http://unity.codeplex.com) to inject the dependancy of entity context.
[Dependency]
public Context { get; set; }
}
public calss ItemRepository : BaseRepository
{
public List<Items> Select()
{
IEnumerable<Items> items = from item in Context.Items select item;
List<RealItem> lst = new List<RealItem>();
foreach(itm in items)
{
MemoryStream stream = new MemoryStream(itm.Image);
Bitmap image = (Bitmap)Image.FromStream(stream);
RealItem ritem = new RealItem{ Name=item.Name, Image=image };
lst.Add(ritem);
}
return lst;
}
}
Is this a correct way to use the repository pattern? I'm learning this pattern and I've seen a lot of examples online that are using a repository but when I looked at their source code... for example:
public IQueryable<object> Select
{
return from q in base.Context.MyItems select q;
}
as you can see almost no behavior is added to the system by their approach except for hidding the data access query, so I was confused that maybe repository is something else and I got it all wrong. At the end there should be extra benifits of using them right?
Update: as it turned out you don't need repositories if there is nothing more to be done on data before sending them out, but wait! no abstraction on LINQ query? that way client has to provide the query statements for us which can be a little unsafe and hard to validate, so maybe the repository is also providing an abstraction on data queries? if this is true then having a repository is always an essential need in project architecture!! however this abstraction can be provided by using SQL stored procedures. what is the choice if both options are available?
Yes, that's the correct way: the repository contract serves the application needs, dealing ony with application objects.
The (bad)example you are seeing most of the time couples any repository implementation to IQueryable which may or may be not implemented by the underlying orm and after all it is an implementation detail.
The difference between IQueryable and IEnumerable is important when dealing with remote data, but that's what the repository does in the first place: it hides the fact you're dealing with a storage which can be remote. For the app, the repository is just a local collection of objects.
Update
The repository abstracts the persistence access, it makes the application decoupled from a particular persistence implementation and masks itself as a simple collection. This means the app doesn't know about Linq2Sql, Sql or the type of RDBMS used, if any. The app sends/receives objects from the repo, while the repo actually persists or loads objects. The app doesn't care how the repo does it.
I consider the repository a very useful pattern and I'm using it in every project, precisely because it marks the boundry between the application (as the place where problems and solutions are defined and handled) and storage/persistence where data is saved.
You can make you repository a generic one and can get mode value out of it. And make sure you are using an Interface (IItemRepository ) to access repositories in manager layer so that the you can replace your repositories with some another data access method using new repository implementation. Here is an good example how to do this.

Resources