I have an Oracle DB set up, and the Database has a bunch of Views.
The view GFL_BUYERS_ID_V has 2 columns of EMPLOYEE_ID and FULL_NAME. The database is already filled before I created the mvc project.
I Add the database successfully and added the a schema modelBuilder.HasDefaultSchema("examplename."); to my context because when I use SQL to retrieve data, I need to do:
SELECT * FROM "examplename".GFL_BUYERS_ID_V
for it to work, I assume that is what it's for. Apologies in advance I am new to .net, mvc and connecting databases.
The following crashes at the .Select and tells me that value cannot be null (I have no clue what is returning a null value, if I inspect values in context->GFL_BUYERS_ID_V when it breaks, in Local there are 0 values, and in Result View it contains all the appropriate one's, I assume this is relevant info but I don't know how to use it):
var model = new EmployeeModel();
using (var context = new OracleContext())
{
model.Buyers = context.GFL_BUYERS_ID_V.Select(s => new EmployeeModel.Buyer
{
BuyerId = s.EMPLOYEE_ID,
FullName = s.FULL_NAME
}).ToList();
}
return View(model);
this is my object:
public class EmployeeModel
{
public int EmployeeModelId { get; set; }
public List<Buyer> Buyers { get; set; }
public class Buyer
{
public int BuyerId { get; set; }
public string FullName { get; set; }
}
}
I know there is a connection to the database and I can query it via VB. I have fiddled enough with the connection string to know it is correct.
Edit: Scratch that I have no clue if my program is able to connect to the Database or not.
Screen shot of the error
If you would like me to provide more information, I will be happy to, really want to make this one work.
Edit 2: This seems like some sick joke clearly it shows a count: how
Is there an inner exception which is causing the ArgumentNullException?
You are definitely thinking along the right path, so I would break it down into manageable pieces:
1) confirm DB connectivity
2) confirm context is valid, which would most likely only be invalid if no DB connectivity
3) confirm GFL_BUYERS_ID_V is showing data
4) then do the projection to a different model
So the problem was in the Database server not the code. For some reason it used an old default schema variable that wasn't used for a long time.
Related
I am very new to the MVC,Entity framework application and am still learning. I have a query.
I am inserting the values in SQL server database using Entity Framework and MVC application with the stored procedure. I am using the DB first approach. I want to ask why I need to add an select statement even though I have written the procedure to insert the values. If I dont write the select statement then it throws the error.
An exception of type 'System.Data.Entity.Core.EntityCommandExecutionException' occurred in EntityFramework.SqlServer.dll but was not handled in user code
Additional information: The data reader is incompatible with the specified 'EmployeeDBModel.Employee'. A member of the type, 'Id', does not have a corresponding column in the data reader with the same name.
ALTER PROCEDURE [dbo].[sp_InsertEmployees]
-- Add the parameters for the stored procedure here
#FirstName varchar(50),
#LastName varchar(50),
#Address varchar(50),
#Salary int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
Insert into Employee values(#FirstName,#LastName,#Address,#Salary)
--select scope_identity() as Id,Firstname,LastName,Address,Salary from Employee
END
If I uncomment select command it just work.
Note:- Id is identity column and auto seed is true
Model :-
public partial class Employee
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public Nullable<int> Salary { get; set; }
}
Controller:
[HttpPost]
public ActionResult Create(Employee emp)
{
using (EmployeeDBEntities db = new EmployeeDBEntities())
{
if (ModelState.IsValid)
{
db.InsertEmpDetail(emp.FirstName, emp.LastName, emp.Address, emp.Salary);
db.SaveChanges();
ViewBag.Message = "New Employee Created Successfully!!";
}
}
return View(emp);
}
I have created the function InsertEmpDetail and mapped it properly.
I think if I dont remember it wrongly , when you map you entity, the orm entity framework will need to be able to read for the entity through certaion way. (sorry cant get to my net computer, but in java it often the same).
I'm guessing that your procedure have return result thus the will be read onto the entity.
another possibililty is the commit of the stored procedure, since it cant be read after insert properly, the column seems to be missing.
(just saying this have happen to me before)
good luck,
edd
I have two repository functions for adding and removing favorite products for a customer.
public void AddProductToCustomer(int customerId, int productId) {
var customer = _customers.GetById(customerId,
new []{ModelContents.FavoriteProducts});
var product = _products.GetById(productId);
customer.FavoriteProducts.Add(product);
_context.SaveChanges();
}
and
public void RemoveProductFromCustomer(int customerId, int productId) {
var customer = _customers.GetById(customerId,
new[] { ModelContents.FavoriteProducts });
var product = _products.GetById(productId);
customer.FavoriteProducts.Remove(product);
_context.SaveChanges();
}
When I run locally against the production database it works fine but once I publish the code the _context.SaveChanges() fails to update the database. I have debugged this code remotely and there is no error thrown or returned from the function. Has anyone else seen this behavior before?
[UPDATE] By fails I mean that the database is not updated with the changes to customer.FavoriteProducts. Products are not added or removed from the list respectively and the total count of FavoriteProducts never changes, but only when the code is published, not when I am running it on my dev machine against the same database.
I hope that helps
[UPDATE] It occurred to me that people might wonder what the line new []{ModelContents.FavoriteProducts} refers to. This is a enumeration that tells the customer repository which navigation properties to populate for the model. The Customer is a large object and I don't always want all of its data. I have verified that customer.FavoriteProducts is populated in these cases.
[UPDATE] One thing that might be related to the issue is that the Product Model also has a Product.FavoritedBy Navigation Collection that contains the number of Customers that have Favorited that Product. Just like Customer.FavoriteProducts it is always up-to-date when I add or remove from a Customers FavoriteProducts collection except after the application is published to the server. The Entity Relationship is:
modelBuilder.Entity<CustomerUser>()
.HasMany(u => u.FavoriteProducts)
.WithMany(f => f.FavoritedBy)
.Map(t => t.MapLeftKey("UserId")
.MapRightKey("ProductId")
.ToTable("FavoriteProducts"));
Try the following in your AddProductToCustomer method:
_context.Entry(customer).State = EntityState.Modified;
_context.SaveChanges();
I use MVC5. I've got some issue with file uploading using HttpPostedFileBase. I've got a form where I can can choose a file from my disk and type some information about it(in textbox). When I submit a form the controller action is called. In this action I open file and check if it has some specific data(related with data from textbox). So I do some validation here. I can't do it using JQuery - it's complex. The server side validation is the only option. Finally if validation fails I return model(with file) to the view but after that I've got validation error next to file field but file field is empty. I've read that's hard to return file to the view. I don't want to use ajax to upload file. I want to do it simple. If you got an article that can help, please share it with me.
How can I solve my problem?
I know you mentioned not using AJAX to do file upload, but I think this solution is a very simple one.
Using the following jQuery plugin (https://blueimp.github.io/jQuery-File-Upload/), you can automate that process and if there are any validation issues in your file, then you can return the following model with the error.
string errors = "Errors returned from complex logic";
if (!String.IsNullOrEmpty(errors))
{
// error response
status = new ViewDataUploadFilesResult()
{
name = Path.GetFileName(hpf.FileName),
size = hpf.ContentLength,
error = errors
};
}
Here is the class needed for the response that matches the jQuery file upload documentation: https://github.com/blueimp/jQuery-File-Upload/wiki/Setup
public class ViewDataUploadFilesResult
{
public string name { get; set; }
public int size { get; set; }
public string type { get; set; }
public string url { get; set; }
public string error { get; set; }
}
If I'm understanding correctly, since the file is already on the users computer, you only need to associate the file to the current file they're attempting to upload to returns errors. And to make it so they don't have to reselect the file to upload. I don't see any other reason to need to return the actual file to the user as they already have the file they're uploading.
Looking at this code from here:
[Serializable]
public class CreateClientCommand : Command
{
public string ClientName { get; private set; }
public string Street { get; private set; }
public string StreetNumber { get; private set; }
public string PostalCode { get; private set; }
public string City { get; private set; }
public string PhoneNumber { get; private set; }
public CreateClientCommand(Guid id, string clientName, string street, string streetNumber, string postalCode, string city, string phoneNumber) : base(id)
{
ClientName = clientName;
Street = street;
StreetNumber = streetNumber;
PostalCode = postalCode;
City = city;
PhoneNumber = phoneNumber;
}
}
The Guid here is just relevant for the command. It is not the Guid of the (potentially) created aggregate root. What is the best practice to obtain this Guid and how are any potential validation errors communicated back to the the code that puts a command on the bus? For example like this:
_bus.Publish(new CreateClientCommand(
Guid.NewGuid(),
_clientDetailsReport.ClientName,
_clientDetailsReport.Street,
_clientDetailsReport.StreetNumber,
_clientDetailsReport.PostalCode,
_clientDetailsReport.City,
_clientDetailsView.PhoneNumber));
_bus.Commit();
I understand that CQRS usually implements eventual consistency. This means that it might take a while before the client is actually created. Some MVC/CQRS code uses this approach:
[HttpPost]
public ActionResult Add(DiaryItemDto item)
{
ServiceLocator.CommandBus.Send(new CreateItemCommand(Guid.NewGuid(),item.Title,item.Description,-1,item.From,item.To));
return RedirectToAction("Index");
}
Obviously, the index page might show some grid containing the DiaryItems and the user might be able to see the latest created DiaryItem (potentiality after a while). Any feedback would be very much appreciated. Thanks.
Are you asking about the distinction between an ID for the command itself, versus the ID of the entity it might create? The former would typically be an infrastructure concern, found on something like a message envelope, buried in a RPC protocol, or the like. The latter would be part of your domain. (Though in many cases, it's nice to treat the ID of an entity as an infrastructure concern as well, since you might choose it for convenience in your persistence model.)
The easiest way to do this is to use the guid that you pass on the command as the actual aggregate Id and then you have it to hand and don't have to wait for it to be communicated back down on an event
Not sure why your command has an id it confuses things ( Yes some distributed systems use this but it should be a last resort). Most developers would see this as the id of the aggregate .
Generally just create the aggregate Id and send it with the command . After all the command is creating the Entity ..
Commands should in most cases be sync so you can throw errors back . With async commands you really should have a call back for success or failure ( and async should only be used where you really have the need it adds a lot of cost to the system ) .
You don't move to the next step ( if you need a next step ) until either
A) Its a system that deals with eventual consistency, a lot of business logic does do this. eg waiting for the exchange or a 3rd party to process something , then the work is waiting for that information . ( Ie the command creates an Order but the processing of the order eg OrderDetail may not be there yet and the order has a state of Order Processing)
B) You have success , timeout or failure response to command before continuing .
Visual Studio 2013
I am trying to learn asp.net MVC over at PluralSight. I created a project(dll) called eManagr.Domain with the following classes:
Department / Employee / IDepartmentDatasource
Department.cs
public class Department
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
Employee.cs
public class Employee
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
}
IDepartmentDataSource
public interface IDepartmentDataSource
{
IQueryable<Employee> Employees { get; }
IQueryable<Department> Departments { get; }
}
I created an infrastructure folder with the following file : DepartmentDb.cs
public class DepartmentDb : DbContext, IDepartmentDataSource
{
public DbSet<Employee> Employees {get; set;}
public DbSet<Department> Departments {get; set;}
IQueryable<Employee> IDepartmentDataSource.Employees
{
get { return Employees; }
}
IQueryable<Department> IDepartmentDataSource.Departments
{
get { return Departments; }
}
}
I then created another project using MVC 4 called eManager.Web with Internet Template during the creation of the project.
When running Enable-Migration it says I have two[eWeb.Domain , eWeb.Model.Users] which then I tell it Enable-Migration with the following command:
Enable-Migration -ContextTypeName DepartmentDb
which creates the migration folder and a file called Configurations.cs
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(eManager.Web.Infrastructure.DepartmentDb context)
{
context.Departments.AddOrUpdate(t => t.Name,
new Department() { Name="Engineering"},
new Department() { Name = "Sales" },
new Department() { Name = "Shipping" },
new Department() { Name = "HR" }
);
}
EDIT -- Connection String from Web.Config --
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-eManager.Web-20140216202751;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-eManager.Web-20140216202751.mdf" providerName="System.Data.SqlClient" />
When I run the following I get the following reponse:
PM> update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending code-based migrations.
Running Seed method.
PM>
After this runs, I suppose to see a database file in my App_Data but it does not exist and when I use SQL Server Object Explorer, the database is not created even though that is what I am trying to do.
Could you provide your connection string from Web.config?
Also, is there a Data Connection (Server Explorer -> Data Connections) named the same as your connection String?
I think, adding a parameter-less constructor to your DepartmentDb context class could solve your problem
public DepartmentDb ()
: base("name=DefaultConnection")
Where name=DefaultConnection has to be your connection string name
I noticed that you enabled your migration in the correct way, have you run:
add-migration "give it a name" ?
once this has been completed you will notice a new file in the migrations folder.
you wont be able to update database with out creating a new migration.
I just ran into something very similar. I encountered it when I was going through the following ASP.NET MVC tutorial:
https://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application
In my case, the problem seemed to be that I already had a database table of that name. I had gone through the tutorial partway previously about a month ago, but was interrupted and had to abort. Even though I deleted the entire Project, it seemed that the database table name may have been retained.
I say seemed to be, because the problem disappeared with the following solution: after a 2nd delete of the project, I carefully substituted 'Contoso' for 'ContosoUniversity' in every relevant situation.
Before the problem was solved, I was repeatedly getting the (0x80131904-error) in the Package Manager Console when trying to update-database, and a notice that the mdf file could not be connected to the database. However, when I checked the appropriate directory, the mdf file was not even being created.
FYI For beginning MVC-ers in Visual Studio 2012, I do recommend going through the following MVC tutorial before the one above.
https://www.asp.net/mvc/overview/older-versions/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4
A MVC5 Visual Studio 2013 version is also available through that link.
The tutorial of the first paragraph makes a few jumps...
I could not have debugged the issue if I'd started with the EF5 tutorial as my first MVC project.