Console gets data but API call doesn't when using same method - c#

I'm in the middle of creating a multi-tier application which includes the following layers
API
Business
DAL
-
Entities
All Layers have access to the Entities and also access to the layer that is beneath them in the list.
I also have a Console project.
My problem is that I make a call to the Business layer to get all data from a table, it works fine and retrieves two rows. However, I used the same method inside my API layer and it returns no rows - it also throws no errors and has left me stranded.
These are the classes/methods:
API:
public class CompaniesController : ApiController
{
CompaniesService _companiesService = new CompaniesService();
public IEnumerable<Company> GetAllCompanies()
{
return _companiesService.GetAllCompanies();
}
}
Business:
public class CompaniesService
{
public List<Company> GetAllCompanies()
{
var companyRepository = new CompanyRepository();
return companyRepository.GetAll();
}
}
DAL:
public class CompanyRepository
{
public List<Company> GetAll()
{
//create DBContext object
using (var context = new dbEntities())
{
var data = context.Company.ToList();
return data;
}
}
}
Entity:
[Table("Companies")]
public class Company
{
[Key]
[Column("ID")]
public int ID { get; set; }
public string Name { get; set; }
public string Symbol { get; set; }
public string Exchange { get; set; }
}
I am using Entity Framework 6 on Visual Studio 2013 and using a MySQL Database. Each layer is inside of a different project - just in case this is a reference based problem.

The problem was a simple fix, I simply didn't have the correct connection string inside of the API Project.

Related

No Data is being returned from SQL Database using DBContext

I'm creating a system that draws routes using Bing Maps and ASP.Net. I want to store the postcodes for the stops on the route in a SQL Database and pass them over to the view using MVC.
However, querying the database doesn't return any results, even though the Database is popualted. I've used Debug.WriteLine in various parts of the code and deduced that though it's connecting to the database and querying the right table, when I initialise the DBContext in my controller, using ToList.Count on it shows 0.
My code is as follows:
Controller - MapController.cs
private StopsDBContext db = new StopsDBContext();
public ActionResult Index()
{
Debug.WriteLine("***************************************************************************************");
Debug.WriteLine("--->" + db.Stops.ToList().Count + "<---"); // this shows 0
Debug.WriteLine("***************************************************************************************");
var Stops = from e in db.Stops
select e;
List<Stop> Model = Stops.ToList();
return View(Model);
}
Model - Stop.cs
public class Stop
{
public int ID { get; set; }
public string Name { get; set; }
public string Postcode { get; set; }
public Stop(int iD, string name, string postcode)
{
ID = iD;
Name = name;
Postcode = postcode;
}
public Stop() {}
}
public class StopLists
{
public IEnumerable<Stop> StopList { get; set; }
}
public class StopsDBContext : DbContext
{
public StopsDBContext()
{
Database.Log = s => Debug.WriteLine(s); //this shows the sql queries in the console
}
public DbSet<Stop> Stops { get; set; }
}
I've passed hardcoded data into the view before doing this so I know that part's right, and since it's running the query it must be connecting to the Database, so I'm not sure what I'm missing.
Thanks in advance
EDIT: Updated classes following advice from Dai
I think that you should use the constructor like this way :
public StopsDBContext() : base("name=Connectionname")
I've solved the error now. Thanks to everyone that replied for your advice.
Turns out my model and my table had different fields and I didn't realise, so the DBContext was searching for fields that didn't exist. Whoops.

Entity Framework - Updating entity with added/modified child and grandchild entities

I am not sure if I am doing this the right way or not, so need advice.
I have an entity, this entity has a child collection, and each child entity has another child collection. Something like this (simplified example)
public MyEntity() {
public long Id { get; set; }
public ICollection<MyChild> Children { get; set; }
}
public MyChild() {
public long Id { get; set; }
public long MyEntityId { get; set; }
public MyEntity MyEntity { get; set; }
public ICollection<MyGrandChild> Children { get; set; }
}
public MyGrandChild() {
public long Id { get; set; }
public long MyChildId { get; set; }
public MyChild MyChild { get; set; }
public string Name { get; set; }
}
Now in our application, the user retrieves this entity from our webApi into an angularJs application. The user then updates the entity (and sub entities) and passes the entity back to the webApi. I am using models to pass the objects from my webApi to the angularJs application, and they look something like this.
public MyEntityModel() {
public long Id { get; set; }
public ICollection<MyChildModel> Children { get; set; }
}
public MyChildModel() {
public long Id { get; set; }
public ICollection<MyGrandChildModel> Children { get; set; }
}
public MyGrandChildModel() {
public long Id { get; set; }
public string Name { get; set; }
}
Once the models are passed back to the webApi, I use Auto Mapper to convert them back to entity objects.
Now the bit I am confused about, i now pass the object to my service layer, my method looks similar to this
public Task<int> UpdateAsync(MyEntity updated) {
_context.Entry(updated).State = EntityState.Modified;
return _context.SaveChangesAsync();
}
If I add a new MyChild or MyGrandChild object to MyEntity after MyEntity exists or update MyChild or MyGrandChild object then the changes are not committed to the database? I changed my UpdateAsync method to this, but is this really needed?
public Task<int> UpdateAsync(MyEntity updated) {
_context.Entry(updated).State = EntityState.Modified;
foreach (var child in updated.Children) {
if (child.Id == 0) {
_context.Entry(child).State = EntityState.Added;
} else {
_context.Entry(child).State = EntityState.Modified;
}
foreach (var grand in child.Children) {
if (grand.Id == 0) {
_context.Entry(grand).State = EntityState.Added;
} else {
_context.Entry(grand).State = EntityState.Modified;
}
}
}
return _context.SaveChangesAsync();
}
Do I really have to loop through each collection, and sub collection, check if the id equals 0 and set its state accordingly?
Yes, you have to do that.
When you do all the work inside a DbContext scope it takes care to track al the changes happening in the entities, and you have to do nothing to let the DbContext know whathas changed.
But, in multi-layered applications, when you move the entities between layers they cannot be kept inside a DbContext scope, so you're responsible for tracking the cahnges.
Julie Lerman recommends implementing an interface to track the status of each entity. This interface has a property that keeps the entity status. This is modified on the client side and visited on the server to set each entity status: get the entities on the server side, attach them to the context, and modify its status according to the tracking interface property. (I can't find the reference, but it's covered in her Programming Entity Framework book, and in one of her Pluralsight courses).
Trackable Entities can also be of your interest.
If you want this to happen "automagically" you can use Breeze. This let you easyly expose an EF model on the client side, using JavaScript code. This code is able to track the changes (and do many other things like validating) in the client side, and send them back to the server to update the database. It's quite easy to get started. Basically you need to install the NuGet package for the server to implement a Breeze controllers, which is done with very little lines of code, and the NuGet package for the client, that implements the JavaScript code. It's advisable to use some MVVM JavaScript library, like Knockout or AngularJS, because the changes will be automatically tracked by subscribing to the observables created by these libraries.

Access properties of extending class in a base class query from DB with Entity Framework TPH pattern

Probably the questin title is not self-explanationary.
I have an ASP.NET MVC5 project with Entity Framework 6. I use code first and I've implemented a TPH pattern for an entity.
There's a base Request entity (I've removed most fields, it's just an example).
public class Request
{
public int Id { get; set; }
public string Title { get; set; }
}
also there's some models with exclusive properties that extend it:
public class RequestQuestion : Request
{
public string Question { get; set; }
public string Answer { get; set; }
}
public class RequestForWork : Request
{
public string WorkName { get; set; }
}
Each of them is added to the EntityContext:
public DbSet<Request> Requests { get; set; }
public DbSet<RequestQuestion> RequestQuestions { get; set; }
public DbSet<RequestForWork> RequestForWorks { get; set; }
When I create some of the requests I add them like this:
var db = new EntityContext();
var requestQuestion = new RequestQuestion{ some initialization };
this.db.Requests.Add(requestQuestion);
this.db.SaveChanges();
And here comes the question. When I query requests of the user
var requests = this.db.Students.Find(userId).Requests.ToList();
in debug I can access the properties of the extending class for every request through the base. So, is there a way to somehow get a type of class that is extending the selected entity and to access it's properties?
Currently to build a list of all requests and fill some viewmodel with data I need to seperately select every type of request and fill a global list from these seperate selects.
You need to cast the base type to its subtype and test for null
foreach (r in requests)
{
var rq = r as RequestQuestion;
if(rq != null)
{
string rq = rq.Question
}
var rfw = r as RequestForWork;
if(rfw != null)
{
string wn = rfw.WorkName;
}
}

Implement a Save method for my object

I'm trying to improve my application's design, So instead of calling the DataAccess layer from the presentation layer. I'll try to implement a save method from my object in the BusinessObjects layer. but I'm not sure how to pass the object or it's properties through the layers. for example in my old design I just create an instance of my object in the presentation layer and assign it's properties then just call the DataAccess method for saving this info in the database and pass the object as a parameter as illustrated.
DAL
public static void SaveObject(Object obj)
{
int id = obj.id;
string label = obj.label;
}
PL
Object obj = new Object();
obj.id = 1;
obj.label = "test";
DAL.SaveObject(obj);
but I just want to do this in my PL
Object obj = new Object();
obj.id = 1;
obj.label = "test";
obj.SaveObject();
Is that possible? and how would my DAL look like ?
Edit: Explaining my requirements
I'll base my code right now on a very important object in my system.
BusinessEntitiesLayer uses BusinessLogic Layer
namespace BO.Cruises
{
public class Cruise
{
public int ID
{ get; set; }
public string Name
{ get; set; }
public int BrandID
{ get; set; }
public int ClassID
{ get; set; }
public int CountryID
{ get; set; }
public string ProfilePic
{ get; set; }
public bool Hide
{ get; set; }
public string Description
{ get; set; }
public int OfficialRate
{ get; set; }
public string DeckPlanPic
{ get; set; }
public string CabinsLayoutPic
{ get; set; }
public List<Itinerary> Itineraries
{ get; set; }
public List<StatisticFact> Statistics
{ get; set; }
public List<CabinRoomType> RoomTypesQuantities
{ get; set; }
public List<CabinFeature> CabinFeatures
{ get; set; }
public List<CruiseAmenity> Amenities
{ get; set; }
public List<CruiseService> Services
{ get; set; }
public List<CruiseEntertainment> Entertainment
{ get; set; }
public List<CustomerReview> CustomerReviews
{ get; set; }
}
}
BusinessLogicLayer uses DataAccessLayer
Actually this layer is intended to be validating my object then call the DAL methods but I didn't implement any validation right now, so I'm just using it to call the DAL methods.
public static void Save(object cruise)
{
CruisesDAL.Save(cruise);
}
DataAccessLayer trying to reference BussinessEntities but it's giving me circular dependencies error!
It's supposed to receive the object and cast it as Cruise entity
public static void Save(object cruise)
{
Cruise c = cruise as Cruise;
//access the object c properties and save them to the database
}
Code sample from my project:
public static List<Cruise> GetCruisesList()
{
string commandText = "SELECT ID, Name + CASE Hide WHEN 1 Then ' (Hidden)' ELSE '' END AS Name FROM Cruises";
List<Cruise> cruises = new List<Cruise>();
Cruise cruise;
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
using (SqlCommand command = new SqlCommand(commandText, connection))
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
cruise = new Cruise();
cruise.ID = Convert.ToInt32(reader["ID"]);
cruise.Name = reader["Name"].ToString();
cruises.Add(cruise);
}
}
}
}
return cruises;
}
PresentationLayer uses BusinessEntities
Input controls (TextBoxes, DropDownList, etc)
When the save button is clicked I take all the values, create a Cruise object and call Cruise.Save();
You should avoid mixing the domain model with the persistence logic.
The examples given above would make a tight coupling solution.
In order to achieve the .SaveObject() you can make extension methods in the BL that would do the job.
BL.*
public static class ObjectPersistanceExtensions{
public static SaveObejct<T>(this IBaseEntity obj){
IObjectDal<T> _dal = AvailableSerices.Obtain<IObjectDal<T>>();
_dal.AddObject(obj);
_dal.Commit();
}
}
So in this way you can still add functionaries to the domain objects without coupling the logic in the domain objects.
Passing the object itself to the data layer is usually a bit funky. Instead, I recommend that you have the object do the talking to the data layer, and let the data layer do its thing.
internal static class DataLayer {
public static bool Update(int id, string label) {
// Update your data tier
return success; // bool whether it succeeded or not
}
}
internal class BusinessObject {
public int ID {
get;
private set;
}
public string Label {
get;
set;
}
public bool Save() {
return DataLayer.Update(this.ID, this.Label); // return data layer success
}
}
The reason you would do it this way, is because your data layer may not have a reference to your business object, and thus would have no idea what it is. You would not be able to pass the object itself. This is a usual scenerio because generally it is your business object assembly that references your data layer assembly.
If you have everything in the same assembly, than the above does not apply. Later on however, if you decide to refactor your data layer into its own module (which is often how it turns out, and is good design), passing the object will break because then it loses its reference to your business object.
Either way you do it, you should know that you will have to update both your object and your data layer if you add a new field or member. That's just a given when you add something new.
I may write a blog on some good design practices for this, but that is my recommendation.
if you follow this pattern you will have the saving logic inside the object definition itself, so when you call from PL:
obj.SaveObject();
this will happen in the Object itself:
public void SaveObject()
{
DAL.SaveObject(this);
}
and your DAL stays the same as you shown above.
it's a matter of design, I would not put the logic of saving inside the object but I would have a BusinessManager or an ObjectMapper to read from DAL and save to DAL.
in general is a good practice to have read or load and Save in the same place, BusinessObject or BusinessManager, but together so you find them easily and update both in a breeze if you add or change a field.

Connect other models with user in Silverlight Business Application

I'm having a real trouble with what I need to do.
Here's the thing:
I'm creating Silverlight Business Application. I want users to be able to define their own "reminders" and "templates". It seems very simple, just 3 models, 2 one-to-many relations and that's all. But I have no idea how I can connect the existing User model to other models.
I tried to create my own "membership" provider - I've created db with all 3 models and it seemed to be ok, I created EntityModel, but now I have 2 different places where User class is defined, and in the first one it inherits UserBase class and in another EntityObject (in the file Model.Designer.cs, which is generated automatically.
I'm totally confused - can I stick with the EntityObject solution, delete other definitions of classes? If so, how can I still be able to use all the features that come with silverlight business application? (Authentication/Registering etc. is already provided).
We have implemented this scenario in our LOB app.
Firstly add the appropriate properties to the user class like so.
public partial class User : UserBase
{
public Guid UserId { get; set; }
public int PeopleId { get; set; }
public int EpothecaryUserId { get; set; }
public string PersonFullName { get; set; }
public SearchGroups SearchGroups { get; set; }
public string SearchHistoryString { get; set; }
public int SearchRowsReturnedPerGroup { get; set; }
}
Then create a class derived from AuthenticationBase
public class AuthenticationService : AuthenticationBase<User>
{
protected override User GetAuthenticatedUser(IPrincipal principal)
{
return base.GetAuthenticatedUser(principal).WithProfile();
}
[Invoke]
public void SaveMyUser(User user)
{
if (user.UserId == Guid.Empty)
{
ClientLogger.Error("SaveMyUser failed because the UserId is invalid");
return;
}
using (var db = new Pharma360Model())
{
var userProfile = db.UserProfiles.Single(p => p.EpothecaryUserId == user.EpothecaryUserId);
userProfile.SearchGroups = (int)user.SearchGroups;
userProfile.SearchHistory = user.SearchHistoryString;
userProfile.SearchRowsReturnedPerGroup = user.SearchRowsReturnedPerGroup;
db.SaveChanges();
}
}
}
And this will take care of the loading and saving of the custom User class.

Categories