So, I don't know if the question is explicit enough, but here's my problem:
I am writing a small application in VB.Net, that retrieves information from a website and present it to the user. Basically, I have written a class, which has a Get(URL) method which retrieves the webpage, reads it and populates the various Properties (Read-only) of the object.
This class works OK.
Now, I would like to store that information in a Database (I'm using Access for now), so that I can read the data from the DB, if the class gets called for a known URL. As I'm fairly new to OOP and completely new to DB usage in desktop applications (no problems in designing the DB though), I am not sure on how to proceed:
Should I put the database code in my existing class?
Should I create an extended class based on the existing one, adding the DB code?
Should I create a completely different class for the DB data and put the switch logic (read from DB or from web) in my application?
...
I realize that my question may sound silly to the most experienced of you, but I'm new to this and I would really like to learn how to do things the right way the first time!!!
Thanks!
This is what I would do:
Create a new class for the database code, and create an
interface for it that it implements.
Then create another class that has the code to fetch the web data. Make it implement the same interface.
Now you can subsitute either class to do your data access from your controller class.
Also, I usually put database and data access in separate projects from my service and ui classes, which are in their own classes, but that might be overkill for your situation.
If you'd like to read more on the subject, look up n-tier application design. The tier you're talking about here is data access.
http://en.wikipedia.org/wiki/Data_access_layer
Related
I am developing an application with Asp.Net core 5 and the application accesses and displays information from two different databases(both Sql). One database is application’s own database where all the information will be stored/added. But there is another database already exists(on-prem server) and being used by another application. I want to read some master data from this database to use in my application. So I want to connect to the second database to just read master data and display it in application pages. For the first database connectivity I have created a separate entity project using Entity Framework Core 5.0 Code first approach.
How do I access second database just for read data purpose, Which would be the feasible approach for this. I was thinking to create another entity project with EF Core 5 DB first approach, but with this approach it creates DBContext class and all DbSets objects for each table. Which is not required I feel because I just want to read 8-10 tables from the entire database
Can anyone please suggest which would be a better approach for this? DB first approach or Ado.Net Vanilla method?
Finally I am going to reference these entity projects into my Web API application for all DB operations.
Thanks!
Within the same project, next to your existing dbContext, register a new extension of db context that will encapsulate the second database that you want to read from.
Do not copy the entire project from the start, rather think that the only reason to have a second dbContext to start with, is when dealing with multiple databases.
The rest of your code can remain re-usable ( probably ) and you dont need to cope with an other project as well
EDIT:
For example you might register your current context like below:
services.AddDbContext<ApplicationDbContext>(
options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));
You can create a new class, lets say
public class OldDataDbContext : DbContext
{
public OldDataDbContext(DbContextOptions<OldDataDbContext> options)
: base(options)....
....
....
on that new dbContext class, register all the dbSets that you are going to read from that master db.
Then register that "new implementation of db context" with the connection string for the other database.
services.AddDbContext<OldDataDbContext>(
options => options.UseSqlServer("name=ConnectionStrings:OldDatabaseConnection"));
Now next to your DefaultConnectionString appSetting ( or however else you might have called it, add an other line with the other connectionString, with keyName "OldDatabaseConnection" and you can use that new class just as you use the old one.
I have Umbraco 7 website with MVC.
I want to perform some custom action on the database.
As I understand I should be using DbContext to connect.
I have referenced System.Data.Entity to get to DbContext class. However when I'm trying to use DbContext I'm getting an error saying
The type or namespace name 'DbContext' could not be found (are you missing
a using directive or an assembly reference?)
In my models namespace:
public class umbracoDbDSN : DbContext
{
//some code
}
Can you let me know what I am missing?
Thanks
You are mixing things up. Umbraco uses PetaPoco as ORM, not entity framework. You don't need to include the System.Data.Entity. Neither you need the DbContext.
However, if you have existing DataLayer logic which you need to incorporate, for legacy systems, you might need to continue with your code above. Then look for entity framework tutorials on the internet to continue your journey.
If you are not dragging legacy stuff, then the question is: do you want to perform queries on custom tables or do you want to query the Umbraco tables for some reason.
Let's start with the last one. Querying the umbraco tables:
If you want to connect to the umbraco SQL tables, I start wondering why. There is a ContentCache, which is blasting fast, and it enables you to query very quickly everything you need from the content section. You have API's for relationships, media, users, members and everything you need. So the question remains, WHY would you ever connect to the umbraco tables.
However, if you want to store data in custom tables, I would read this article of Warren: http://creativewebspecialist.co.uk/2013/07/16/umbraco-petapoco-to-store-blog-comments/
The idea is simple, you reuse the existing code base to extend umbraco behaviour without storing stuff in the content section.
Below a simple example for reusing the databaseconnection while querying some proper created table...
var db = ApplicationContext.Current.DatabaseContext.Database;
// Fetch a collection of contacts from the db.
var listOfContacs = db.Fetch<Contact>(new Sql().Select("*").From("myContactsTable"));
I would like to use a local SQL Server CE in my app; I've read that using EF code-first I can let the system create the db starting from POCO classes; I've configured EFCodeFirst.SqlServerCompact using NuGet but it's not clear to me how can I use it in my WPF app....can anyone help me?
It doesn't really matter whether you use the default WPF style application development or MVVM pattern, as long as you have a separate data layer.
Your data layer should hide away all of the DB implementation logic, including the creation of the DB from the rest of your code.
You could implement it using the Repository pattern, but as long as it provides a known interface and definitions for the data objects that your business logic requires you should be okay.
Note that the data objects used by the other layers of code do not need to be the same as the POCO objects used by the DB.
If you have your data layer accessed by a Singleton class that implements the layer's interface then you could automatically call the DB creation code if the DB can not be found when DataLayer.Instance (for example) is called.
The important thing to remember is that only the internal workings of the datalayer should know where the data comes from the rest of your code should be DB agnostic, only caring that it has the data that it needs, not where it comes from.
As for practicalities here's a link that gives a Code First with EF example.
I have a class running in a winforms app which uses EF Code First. The DbContext is created via DI through the class constructor. All works well.
The problem is the data being referenced is also being modified via a web site, using the same DI pattern with EF Code First, and the data changes are not being reflected in the context instance in the winforms app.
I can solve this by recreating the DbContext object in winforms every time I access it, but seems to be more of a service location pattern to me?
Is there a true DI technique to achieve this?
Or should I remove the context from the DI and use service location?
Were you not happy with the answer to your other question (http://stackoverflow.com/questions/7657643/how-to-force-ef-code-first-to-query-the-database) which suggested using Detach, AsNoTracking or Overwrite Changes?
1) Maybe you could pass an interface that has the ability to create a DbContext, instead of the context itself.
using(var context = _contextFactory.Create()) {
var entity = from table in context.Blah...;
}
The Create method could either create the concrete class itself (defeating the DI pattern a bit), or use service location to have one created for it. Not that nice, but it's better than embedding service location calls everywhere and still means you're controlling the lifecycle yourself.
2) Change the WinForm to read from a webservice run by the website, effectively similar to disabling caching.
3) Deep in the heart of MVC (well not really that deep) it is referencing the DI container directly and using it as a service locator to pass as arguments for newly created objects. Technically you could do something similar in WinForms, but it would need you to split your application up into little chunks (controllers) that don't have a very long lifetime. Maybe it's worth looking at some MVC/MVP frameworks for WinForms, although I found myself cringing at most I saw after a quick google.
The problem is the data being referenced is also being modified via a web site, using the same DI pattern with EF Code First, and the data changes are not being reflected in the context instance in the winforms app.
This is a problem with your expectations.
If your web service and window forms app are in separate processes, they won't share in-memory data.
If you want to sync their in-memory data, simply re-query in one context after committing to the database in the other. This is the same as trying to share data between different SQL connections.
I can solve this by recreating the DbContext object in winforms every time I access it, but seems to be more of a service location pattern to me?
If you want to recreate the DbContext repeatedly, you could use an abstract factory to allow manual re-creation of the object, yet allow you to inject the specific implementation into the factory.
This is not (necessarily) the Service Locator pattern, and you would have to ensure that you manually dispose your DbContext instances. I'd give you some example code, but different DI containers have totally different ways of accomplishing a factory pattern.
Or you could simply make sure that you commit your data on the web service side, and re-query the data on the WinForms app side.
I have quite a deal of experience programing with VB6, VB.NET, C# so on and have used ADO, then SubSonic and now I am learning nHibernate since most of the prospective jobs I can go for use nHibernate.
The thing is, I have been programming based on what I have been taught, read or come to understand as best practice. Recently, someone through a spanner in the works and had me thinking. Up until now, I have been accessing the database(s) from both the core applcation and attached DLLs that I write.
What this persons said ends as follows and hence my question:
I can tell you
that you wouldn't normally want to do this - an external class library shouldn't have access to the database
What I was trying to do was to have a shared/static class for nHibernate sessions that could be consumed in both the global scope of the app and from any dll. This class was to be in a "core" DLL which all dlls and the application reference. Like I said I'm learning nHibernate so it may not be the way.
To say i'm questioning my database access methods is putting it lightly.
Can anyone put me straight on this?
Edit:
I suppose looking at what has been commented already, it depends on how the database is being accessed. I would tend never to put username/password credentials etc hardcoded in any DLLs for any means.
More specifically, my query is in relation to NHibernate's sessions. I have a static class, an helper class, which is called at application start and the new session is then created and attached to the current context, in the case of web applications, and then whenever I need the session I call "GetCurrentSession". This static class is in the "core" dll and can be accessed with any DLL etc that references. This behaviour is intended. My only question is is this ok? Should I be doing it another way?
A couple of reasons would be
Access to the database, how do you cover off username/password
sharing the DLL, a "bad" application may get hold of your DLL and link with it to get access to your database.
Saying this, if you have proper security on files, etc. then I would have thought using a DLL would probably be a reasonable way to go.
Assuming that the username and password are not stored directly in the DLL (but maybe passed as parameters, or passed as a complete connection object) this isn't so bad.
The possible bad practice here might be accessing the same database for the same purpose from different places - core app and DLL. This could get confusing quickly to a new developer, unless the separation is clear and logical.
Myself, I might try to move ALL (or almost all) data access to a DLL just for that purpose, then have the serious application logic (or as much as possible) in the core app or yet another DLL.