ASP.Net MVC 3 with Oracle - c#

I am working on a project using Asp.net mvc 3 and planning to have oracle 11g database as back-end.
I was able to access oracle server with no problem and data loaded successfully into an html table.
The problem comes when I try to add, edit or delete a record. I believe it is a very simple issue, but till now, I couldn't figure it out. The following simple model is used:
class Country
{
public int CountryId { get; set; }
public string CountryName { get; set; }
}
The CountryId feild was created at Oracle using NUMBER(10) as I thought this will work as SQL Server Integer. But an exception was raised, indicates that it couldn't take the value as Edm.decimal !
I tried to make it NUMBER(19) and changed the CountryId to long and still getting the same exception.
I spent long hours searching for an open source project that is using asp.net mvc with oracle, but I couldn't find any!
Any idea, why oracle is not supporting integer, long? how to make it working as expected with my MVC project?

From Oracle Data Type Mappings,
This data type is an alias for the NUMBER(38) data type, and is
designed so that the OracleDataReader returns a System.Decimal or
OracleNumber instead of an integer value. Using the .NET Framework
data type can cause an overflow.
So, you need to use decimal datatype in .net framework to support the NUMBER datatype in Oracle.
It would be better if you mapped your data type in following way:
[.NET: Int32] = [Oracle:NUMBER(2)..NUMBER(9)*]
[.NET: Int64] = [Oracle:NUMBER(10)..NUMBER(18)*]
[.NET: Double] = [Oracle:NUMBER(x, 0)..NUMBER(x, 15)*]
[.NET: Double] = [Oracle: FLOAT]
[.NET: Decimal] = [Oracle:NUMBER]

Have you tried using a decimal or an Int32? I am getting my suggestions from some documentation that I found online: http://docs.oracle.com/cd/E11882_01/win.112/e18754/featLINQ.htm . Let me know how this might work for you.

Related

EF Core Optional Column Treated As Required

I need to read the result from a stored procedure called from EF Core that includes things intended for spreadsheet formatting purposes such as rows with only null values. My code is mostly working, but there are two columns that cause the query to fail when I include them.
Here's my model class (only a few props included for brevity):
public class StoredProcRecord
{
[Column("Prod Line")]
public string ProductLine { get; set; }
[Column("Current Sales")]
public decimal? CurrentSales { get; set; }
[Column("Current Margin $")]
public decimal? CurrentMargin { get; set; }
}
Here's a snippet of part of the output if I run the stored procedure from SQL Server Management Studio:
Here's how I registered the type as an entity model with EF Core in the db context:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Query<StoredProcRecord>();
}
Here's how I'm calling the stored procedure:
return _context.Query<StoredProcRecord>().FromSql("EXECUTE my_stored_proc").ToList();
In this example, EF Core always throws an exception when trying to call FromSql() with a message stating:
The required column 'Current Margin $' was not present in the results
of a 'FromSql' operation.
According to the EF Core docs, as long as a column is nullable, then it is not required. Yet, I receive that exception that claims "Current Margin $" is required. It also only happens with the CurrentMargin property, not the CurrentSales property, which uses the same type. If I remove CurrentMargin, the whole thing works fine and I'm just missing that one property.
I have tried using [Column(Order = 2)] instead of a named column, thinking maybe the dollar sign in the column name had something to do with it, but that results in:
The required column 'CurrentMargin' was not present in the results of
a 'FromSql' operation.
Including both order and name results in the same type of error.
Worth noting, this is not a stored procedure that I have the option to make updates to.
What is different about the CurrentMargin property compared to CurrentSales that causes it to fail like this? Is there some special way I need to handle the dollar sign in the column name? Am I missing something else completely?
Edit:
Here's a snippet from the very end of the stored procedure where the resulting table is output. I'm including this to show that "Current Margin $" is indeed one of the column names. I actually copied/pasted right from the stored procedure just to make sure I hadn't mis-typed the column name.
BEGIN
-- bulk of stored procedure that builds #tmp_tbl omitted for length
SELECT
'Prod Line' = pl_key,
'Current Sales' = curr_sales,
'Current Margin $' = curr_margin
FROM #tmp_tbl
END
The embarrassing answer to this question is make sure you read your code carefully, especially things like string values.
In this case, I have two stored procedures that will eventually get used by my app, bv_xls_profit_sum_v2 and bv_xls_prod_sum_v2. I was implementing usage of the results of the first stored procedure, but I accidentally provided the name of the second stored procedure to EF. The columns from those two do not match, so the error I was receiving about missing required column wasn't about whether or not the column was nullable, but was actually a case where the column was indeed missing from the result set completely. This wasn't obvious when testing through SQL Server Management Studio because I didn't realize I was running a different stored procedure.
Bonus "Answer":
Prior to figuring out my stupid mistake, I did figure out a workaround that I'll leave here just in case it proves useful for anyone. My app has its own SQL Server instance, but also queries against another SQL Server instance that is not controlled by the app (that's where the stored procedures in question live). To work around the issue I was struggling with, I connected the other SQL Server instance to mine as a linked server. I then duplicated the stored procedure I wanted to call, updated it to have it query the linked server, eliminate unwanted null rows, and return using column names to match my model class. This does work and allows me to manage the stored procedure, though it does likely add additional latency to getting a result set back from querying the modified stored procedure.

How to define the Bit datatype in a method parameter in C#?

I have a SQL table on a database which has a column in it with the Bit datatype. I'm trying to define a method in my C# application which takes two of the columns from the table and uses them as parameters.
Here is the code
public void Edit_NAA_ApplicationsFirm(int ApplicationId, string UniversityOffer, bit Firm)
{
//This line declares a variable in which we store the actual values from NAA_Applications based on the associating ID
NAA_Applications AppFirm = Get_Applicant_Application(ApplicationId);
//Here we tell the application that the values edited are equal to the values within the table
AppFirm.Firm = Firm;
//Any of these changes are then saved.
_context.SaveChanges();
}
The only issue is the the program keeps trying to convert bit to BitConverter. When I change it to bit it has issues accepting it as a datatype.
It should be worth noting I'm building the application in an ASP.Net Framework solution.
Could anyone tell me what it is I'm doing wrong? Am I just referring to the datatype wrong?
Looks like you're using Entity Framework.
It'll use a .NET boolean to represent a T-SQL bit. That would be a sensible way to do it for any other data access method as well. boolean true will convert to 1 in the bit field, and false to 0.
In fact it's even documented, more than once, that this is the correct .NET CLR type to use. See https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/linq/sql-clr-type-mapping , https://msdn.microsoft.com/en-us/library/cc716729(v=vs.100).aspx and probably others.
So in your case bool Firm would be appropriate.
The correct datatype for bit in c# is boolean. so
public void Edit_NAA_ApplicationsFirm(int ApplicationId, string UniversityOffer, bool Firm)
if I understand corectly, try use bool Firm
in c#, value 1 from database is converted to "true", and "true" from code is converted to 1 in database

Timestamp column in sql to valid string representation

I have a table with Column data type "timestamp" in sql server.
Currently I am trying to get the data from this table to sqlite database. as it needs only string value. So far i have not been able to find correct way to convert to string.
So for example my SQL Value is 0x0000000000012DE0
When I get the record using entity framework, I get byte array.
Tried to convert using following code to string.
value = BitConverter.ToInt64(Version, 0);
However for same record, i get 0xE02D010000000000
This is one difference.
The second, Since I am working on azure mobile app, and this data also goes to android via WebAPI controller.The result I get from fiddler is something in this format
AAAAAAABM8s=
I want to also convert the byte arrray value in above format .
Any suggestions?
I had a similar issue with my ASP.NET Core, EF Core 2.0, Angular 2 app. This was a database first development and changing the database definition was not within my remit.
In my case, EF Core automatically performed the concurrency check for me where the Timestamp column was present in the table. This was not an issue for updates because I could pass the DTO in the body but with deletes I could not.
To pass the timestamp I used a query string. The value being the Base64 string representation of the timestamp e.g. AAAAAAACIvw=
In my repository layer I convert the string back to a byte array e.g.
byte[] ts = Convert.FromBase64String(timestampAsBase64String);
Then delete using the create and attach pattern (thereby eliminating any chance of lost updates)
ModelClass modelobj = new ModelClass { Id = id, Timestamp = ts};
_dbcontext.Entry(modelObj).State = EntityState.Deleted;
Thanks to this thread and the CodeProject article Converting Hexadecimal String to/from Byte Array in C# to get this resolved.

How to assign sql timestamp to c# variable in linq query?

I am developing a MVC application. I have one timestamp column in a SQL table. I have one query to retrieve all data from database. I am using LINQ.
Below is my query:
obj = (from c in entityObject.NCT_ProcessAudit.AsNoTracking()
join proc in entityObject.NCT_Process_Settings on c.process_id equals proc.ID
select new returnObject
{
ID = c.ID,
process_id = c.process_id,
icon_id = c.icon_id,
dispaly_order = c.dispaly_order,
updated = c.updated, //c. updated timestamp in sql and updated is datetime as public Nullable<System.DateTime> updated { get; set; }
output = c.output
}).OrderByDescending(a => a.updated).ToList();
When I run above query I get the following error
The specified cast from a materialized 'System.Byte[]' type to a nullable 'System.DateTime' type is not valid.
May I get some help here. Any help would be appreciated. Thank you.
As i wrote in the comments:
The SQL timesatamp type is not exactly as one might guess by its name.
It's actually just a running number that is usually used for row versioning.
In your case, by the name of the field (updated) i guess that you would like to know when was the row updated, thus, it is better for you to use datetime as the type of the field.
All of this by the way is written in MSDN:
Is a data type that exposes automatically generated, unique binary numbers within a database. timestamp is generally used as a mechanism for version-stamping table rows. The storage size is 8 bytes. The timestamp data type is just an incrementing number and does not preserve a date or a time. To record a date or time, use a datetime data type.
In recent versions of SqlServer this type was deprecated and replaced by rowversion

EF: Is it OK to use default value for the created date property?

I want to set the CreatedDate column to the current datetime whenever a new row is inserted, so I made it like this:
public DateTime CreateDate { get; set; } = DateTime.Now;
I tested it and it works just fine, Is this a practical approach? I saw many articles achieve the same with so much code and using fluent API, no one mentioned this simple method?
That depends on what you want to accomplish.
I saw many articles achieve the same with so much code and using fluent API,
Most of those articles will be about adding default values at the database level. You're not doing that. If you insert a row into your table using plain SQL, and don't specify a value for CreatedDate, you'll get an error.
With what you're doing, CreatedDate always needs to be specified in SQL when inserting. But Entity Framework will always specify it in the SQL when inserting, and completely ignore any default value set at the database level.
So if that's what you want -- the default value only gets applied when creating objects through C# -- then what you're doing is totally fine. It may also be written as setting the value from inside the class's constructor.
#Alex Kozlowski raises a good comment though, which is that DateTime.Now may not be the value you expect to be inserted. It depends on which system is running the code. The time zone may be different from your server's, or the clock may be out of sync.
Yes. This feature was added in c# version 6 onwards. This will work from c#-6 onwards only. And that's why you won't find it in many articles.

Categories