I have the following example which will illustrate my question:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
UserService.CreateUser("NewUser");
}
}
public static class UserService
{
public static void CreateUser(string userName)
{
// DB Context created to CREATE the new user
using (var db = new TestEntities())
{
User userToAdd = new User();
userToAdd.name = userName;
userToAdd.jobTitle = JobService.LookupJob(userName);
db.Users.Add(userToAdd);
db.SaveChanges();
}
}
}
public static class JobService
{
public static string LookupJob(string userName)
{
// 'nested' using, which opens up a new connection to 'read'
using (var db = new TestEntities())
{
return db.JobTitlesNames.Single(a => a.userName = userName).title;
}
}
}
public class TestEntities : DbContext
{
}
}
This is a very noddy example of a scenario I have on a bigger scale. I guess my question is: can this method of 'nested' DbContext creations cause application/sql problems in a large scale application. I know that this sort of structure is bad practice, and generally you should use the same DbContext per business transaction ( in this case, the business transaction being creating a new user ), but if the 'nested' DbContext is only used to read data, never modify, is it still dangerous?
The real-world system I have uses this sort of structure massively, occasionally going down to 4-5 levels of nesting. I'm having ( not going to cover it in detail here, this question is more around theory ) database read/commit problems and I'm wondering if this could be the route cause.
Thanks
Related
I have simple classes to saves and get data (not like repository pattern). But while saving data to multiple tables I want to maintain a transaction. So I just went through Unit of work pattern, but that will require me to do a lot of changes. So I'm thinking if my approach will do the same as UOF.
Here's my code:
CalalogueRepository:
public interface ICalalogueRepository
{
void Create(string guid, string fileName);
}
public class CalalogueRepository : ICalalogueRepository
{
private CatalogueContext _catalogueContext;
public CalalogueRepository(CatalogueContext catalogueContext)
{
_catalogueContext = catalogueContext;
}
public void Create(string guid, string fileName)
{
_catalogueContext.Catalogues.Add(new Catalogue
{
CatalogueId = guid,
FileName = fileName
});
}
}
StuffRepo:
public interface IStuffRepo
{
void Create(string guid, List<StuffModel> myStuff);
}
public class StuffRepo : IStuffRepo
{
private CatalogueContext _catalogueContext;
public StuffRepo(CatalogueContext catalogueContext)
{
_catalogueContext = catalogueContext;
}
public void Create(string guid, List<StuffModel> myStuff)
{
//add stuff to _catalogueContext.StuffTable.Add
}
}
Finally a class that does the SaveChanges and Commit:
public class UOW : IUOW
{
private CatalogueContext _catalogueContext;
private ICalalogueRepository _calalogueRepo;
private IStuffRepo _stuffRepo;
public UOW(CatalogueContext catalogueContext,
ICalalogueRepository calalogueRepo,
IStuffRepo stuffRepo)
{
_catalogueContext = catalogueContext;
_calalogueRepo = calalogueRepo;
_stuffRepo = stuffRepo;
}
public void Save (string guid, string fileName, List<StuffModel> myStuff)
{
using (IDbContextTransaction transection = _catalogueContext.Database.BeginTransaction())
{
_calalogueRepo.Create(guid, fileName);
_stuffRepo.Create (guid, myStuff);
_catalogueContext.SaveChanges();
transection.Commit();
}
}
}
I think there is only 1 CatalogueContext throughout the call.
Ok, so as you can see here, AddDbContext is the right way to register it as you wrote in the comment on the question.
Here it says that AddDbContext will register the context as scoped.
And here you can find what scoped means.
Overall I think you are right that your code will use the same context throughout the Save method.
Couple thoughts:
Probably you want to have a try-catch in case an exception is thrown and you want to rollback
If you are not sure if it's working why not try it? You should test your code/application anyways.
Probably this could be done in a better way, but I don't have the context about the rest of your code/application, so I cannot tell. (Not sure what you mean by "...Unit of work pattern, but that will require me to do a lot of changes." for example.)
Now the Create methods not self-contained, meaning if you just want to add a new item to the table it is not enough to call Create, but separately call SaveChanges(). This is not an explicit problem, but has to be kept in mind and might be a little bit confusing for new developers on the project.
Task assigned to me is to refactor a code but should't modify static access modifier of class. I am trying to implement service layer , unit of work , repository pattern . static repository code is below , how can i implement unit of work and repository pattern for a static class? i like to implement a solution applying solid principles and unit testable application.
static class
using System;
using System.Data.SqlClient;
namespace Contoso
{
public static class UsersRepository
{
private static string ConnectionString = #"Data Source=(local); Database=Users;User Id=sa;Password=password;";
public static User Load(int userId)
{
User user = new User();
SqlConnection connection = new SqlConnection(ConnectionString);
connection.Open();
SqlCommand command = new SqlCommand("SELECT * FROM Users WHERE UserId = " + userId,
connection);
var reader = command.ExecuteReader();
while (reader.Read())
{
user.Name = reader["Name"].ToString();
user.DateOfBirth = DateTime.Parse(reader["DateOfBirth"].ToString());
user.Country = reader["Country"].ToString();
}
connection.Close();
return user;
}
}
}
How can i implement unit of work and repository pattern for a static class?
You can leverage the fact that whenever someone calls the code here, they do so via a public entry point. This means that when the caller first enters the class (via said public method), you create a unit of work and dispose of it only when that same method returns a value to the caller (or simply ends).
Something along the lines of:
public static class MyClass
{
public static User LoadUser(int userId)
{
using (var uow = new UnitOfWork())
{
DoSomething(uow);
var user = uow.UserRepository.GetById(userId);
return user;
}
}
}
Essentially, every public method should create, use and dispose of a single unit of work instance. This ensures two things:
Concurrent calls use their own separate unit of work.
No unit of work will ever linger in-memory after the entry method has finished.
This does get trickier when you start using async programming, but I'm omitting that consideration since you never mentioned it either.
i like to implement a solution applying solid principles and unit testable application
It gets slightly trickier when you deal with dependency injection. Static classes do not have an injectable constructor (note: they do have a constructor, but they don't allow for constructor arguments).
So injecting your dependency is going to be... atypical. One solution I can think of is to explicitly set the kernel (I am using NInject here as a matter of example):
public static class MyClass
{
public static IKernel Kernel { get; set; }
public static User LoadUser(int userId)
{
using (var uow = Kernel.Get<IUnitOfWork>())
{
DoSomething(uow);
var user = uow.UserRepository.GetById(userId);
return user;
}
}
}
How you set the kernel (either by setting it explicitly or assigning it a default value directly) is up to you.
Without NInject or any similar library, you could achieve dependency injection using a Func<IUnitOfWork> as your factory method to create a unit of work on demand:
public static class MyClass
{
public static Func<IUnitOfWork> CreateUnitOfWork { get; set; }
public static User LoadUser(int userId)
{
using (var uow = CreateUnitOfWork())
{
DoSomething(uow);
var user = uow.UserRepository.GetById(userId);
return user;
}
}
}
Again, how you set the factory method's content is up to you, e.g.:
MyClass.CreateUnitOfWork = () => new UnitOfWork();
I have tried to figure this out, but I am stuck.
I have a Net Core 2 application with Service/Repo/Api/Angular layers - but now I want to 'bolt on' a console application and access all the goodies I have already built up. I seem to be in a mess of static objects and DI and null parameters. Anyway, here is a simplified version of my code.
namespace SimpleExample
{
class Program
{
private static ApplicationDbContext _appDbContext;
public Program(ApplicationDbContext appDbContext)
{
_appDbContext = appDbContext;
}
static void Main(string[] args)
{
var instance = new Program(); // this doesn't work!
var instance = new Program(_appDbContext); // neither does this!
instance.GetData();
}
private void GetData()
{
Console.WriteLine("Let's read some data! Press a key to continue.");
Console.ReadLine();
var data = "my data";
var result = GetId(data);
}
private string GetId(string original)
{
var data = _appDbContext.Data
.Where(x => x.Name == original.Trim)
.FirstOrDefault();
return data;
}
}
}
I am getting the classic
'An object reference is required for the non-static field'
error. Then from investigating on here I changed things to static and then everything becomes null.
It's not just the DbContext I am trying to inject. I'm also trying to inject
private ManagerService _managerService;
but getting same errors.
Update
If I try
private static ApplicationDbContext _appDbContext = new
ApplicationDbContext();
as suggested a few times below, then I get the error
There is no argument given that corresponds to the required formal
parameter 'options' of
'ApplicationDbContext.ApplicationDbContext(DbContextOptions)'
OK, I have figured this out, and I'll post my answer for anyone else struggling in this situation.
When you launch the console app, your normal startup.cs doesn't execute, so you have to put a lot of that code in your console app.
private static SiteService _siteService;
private static ApplicationDbContext _appDbContext;
public static void Main()
{
var services = new ServiceCollection();
services.AddTransient<ISiteInterface, SiteRepo>();
services.AddTransient<SiteService>();
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer("blah-blah"));
var serviceProvider = services.BuildServiceProvider();
_siteService = serviceProvider.GetService<SiteService>();
_appDbContext = serviceProvider.GetService<ApplicationDbContext>();
GetData();
}
and now your _appDbContext will be available throughout the rest of your console app.
Hope that helps!
Basically, if you do not plan extensive usage of DbContext nor use DI, there is no need for ServiceProvider. Just remember to make DbContext instance short living and use it for single unit-of-work, not longer.
Your context may look like this:
using Microsoft.EntityFrameworkCore;
namespace YourNamespace;
public class ApplicationContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(#"Your conn string");
}
public DbSet<YourType> YourEntity { get; set; }
}
You can pass conn string by ApplicationContext ctor as well. This is nicely explained here by Microsoft .
Then you can utilise your ApplicationContext like this:
// Unit-of-work closed in using statement
// Here you can query/update your DbContext
using (var dbContext = new ApplicationContext())
{
var queryResult = dbContext.YourEntity.Where(....);
}
You can prepare number of such units-of-work as separate methods for querying a database.
Your repository service can consist of these methods.
Then you can instantiate the service as needed.
I would like to improve my .NET project by adding another layer when accessing the database. This is my code:
namespace Company.Models
{
public static class AgencyBean
{
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static String createGUID(string name)
{
DataAccess dataAccess = new DataAccess();
bool exists = dataAccess.checkIfExists(Id);
if(exist)
{
dataAccess.delete(Id);
}
retur "ok";
}
}
}
I placed DataAccess class in a separate folder called "Helpers" and it contains most of my queries:
public class DataAccess
{
public bool checkIfExists(String Id)
{
try
{
SqlConnection cnn = new SqlConnection(dataConnection);
cnn.Open();
SqlCommand check_Id = new SqlCommand("SELECT COUNT(*) FROM TABLE_GUID WHERE ([USER_ID] = #Id)", cnn);
check_Id.Parameters.AddWithValue("#Id", Id);
int UserExist = (int)check_Id.ExecuteScalar();
if (UserExist > 0)
{
return true;
}
else
{
return false;
}
}
catch (SqlException ex)
{
Debug.WriteLine("SQL Exception " + ex);
DisplaySqlErrors(ex);
throw ex;
}
}
}
public class AgentBeanController : Controller
{
// GET: AgentBean
public ActionResult Index(string name)
{
return View();
}
[AllowAnonymous]
[WebMethod]
public string AgentURL() //here we create Agent URL and return it to the view
{
string var = Models.AgentBean.createGUID("TODO");
return var;
}
}
I'm accessing the database pretty much in very direct way. How would it be with a better technique, so this access can be more secure, like accessing thru a service layer?
I'm connecting to a existing sql database in some server and working with MVC architecture in my project.
So here is what I have done in the past.
First, that is your "models" namespace... models should never have database connectivity. Instead you have a seperate class, such as a controller, that hydrates some model.
Second, I've had a "service" class, which hooks up to a "repository" class. The repository class implements an interface to identify the exact "type" of database you're using.. but if that's not a part of your requirements you probably don't need to go that far.
Third, look up dependency injection (aka, DI). There are several frameworks out there. Personally I've used Autofac, but others exist as well to get the job done easier.
Fourth, on your your "controllers", "services" and "respository" classes, implement dependency injection, as well as any interfaces as needed to form a contract.
Fifth, I would use an actual controller namespace and not be working out of your models namespace to be pushing http calls band and forth.... Instead, create an action in your controller class, and instantiate an instance of your "agencyBean", hydrate it with data, and return that model out to your view.
Basically, in a scenario like this you're trying to keep each component doing what it is designated to do... breaking down responsibilities into smaller pieces and focusing on that. Your controller should just "fetch" your model and maybe do some transformations on it as needed or any other business-type logic.
Your service should handle the communication between your controller and your database layer.
Your data access layer (ie, in this case, some "repository" class...) would do all of those new data connections and/or setting up calls to stored procedures or queries.
Doing things this way has a lot of benefit. Some of the big ones are maintainability, readability, code re-use. Sure it makes your project a bit more complicated in terms of files sitting wherever... but that can be a good thing. It's so much better than slamming everything into one single class and have it do everything :)
But, just FYI, this is from an implementation I've done in the past... I'm sure there are better ways but this setup worked quite well for my team and I.
Here is a small example using some of your code you posted. I DID NOT check this for typos and it wouldn't compile, but should help give a general idea of what I'm talking about....
namespace Company.Models
{
public class AgencyBean
{
public AgencyName{get;set;}
public AgencyId{get;set;}
// other properties...
}
}
namespace Company.Controllers
{
public class MyController : Controller
{
private readonly IMyService myService;
public MyController(IMyService myService) // <-- this is your dependency injection here...
{
this.myService = myService;
}
[WebMethod]
[ScriptMethod(UseHttpGet = true)]
public static String createGUID(string name)
{
var model = new AgencyBean();
model.AgencyId = 1;
model = myService.getAgency(agencyBean);
return model;
}
}
}
namespace Company.Services
{
public class MyService
{
private readonly IMyRepository myRepository;
public MyService(IMyRepository myRepository) // <-- this is your dependency injection here...
{
this.myRepository = myRepository;
}
public AgencyBean getAgency(AgencyBean model){
var dataTable = myRepository.getAgencyData(model.AgencyId);
// fill other properties of your model you have...
// ...
// ...
return model;
}
}
}
namespace Company.Repositories
{
public class MyRepository : IDatabaseCommon // <-- some interface you would use to ensure that all repo type objects get connection strings or run other necessary database-like setup methods...
{
private readonly String connectionString{get;set;}
public MyRepository()
{
this.connectionString = //get your connection string from web.config or somewhere else...;
}
public DataTable getAgencyData(int id){
var dataTable = new DataTable();
// perform data access and fill up a data table
return dataTable;
}
}
}
I have a code that uses EF code first that I want to Unit tests in my unit test I want a real empty database in the start of the test so I did:
[TestInitialize]
public void Initialize()
{
Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
}
[TestCleanup]
public void CleanUp()
{
MyContext db = new MyContext();
db.Database.Delete();
}
but because the tests run in parallel this is not work so I did a order test with my tests and it also
has issues because the database sometimes is not dropped because is in use...
Someone have better strategy? I thought maybe each test will create its own database ? if it is good idea how can I achieve this?
Please try this
[TestClass]
public class UnitTestClass
{
private static string testConnString;
[TestInitialize]
public void Initialize()
{
testConnString = GetTestConnString();
using (MyContext db = new MyContext(testConnString, new DropCreateDatabaseAlways<MyContext>()))
{
db.UnderlyingContext.Connection.Open();
}
}
[TestMethod]
public void TestMethod1()
{
}
[TestCleanup]
public void CleanUp()
{
using (MyContext db = new MyContext(testConnString))
{
db.Database.Delete();
}
}
private static string GetTestConnString()
{
SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder();
csb.DataSource = #"MYPC\SQLEXPRESS"; // Replace it with your SQL-server name
csb.InitialCatalog = "DB"+Guid.NewGuid().ToString().Replace("-","");
csb.IntegratedSecurity = true;
return csb.ToString();
}
}
public class MyContext : DbContext
{
private static IDatabaseInitializer<MyContext> _Initializer;
public MyContext(string connString, IDatabaseInitializer<MyContext> initializer = null)
: base(connString)
{
_Initializer = initializer;
}
public ObjectContext UnderlyingContext
{
get { return (this as IObjectContextAdapter).ObjectContext; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (_Initializer != null)
{
Database.SetInitializer(_Initializer);
}
base.OnModelCreating(modelBuilder);
}
}
What does "real" mean? Have you considered using an in-memory DB in your unit tests? With an in-memory DB like SQLite you can set up a fresh DB for each test with relatively little overhead. You can also prepare a test database once, store it to a file, and load it for each test. Check out this answer. And this link. You'll find more if you Google a little.
I would try to avoid relying on an ordering. The tests should be independent from each other to allow for clear traceability from failed tests to issues in the code. A test should not fail only because another test manipulated shared data.
Another concern for me would be performance. With a mandatory ordering parallel test execution is out of the question. And if you use a production-like DB setting for all your tests, they will definitely be much slower than with an in-memory replacement.