Exec Procedure who receive data from Entity Framework - c#

Database in Oracle - View:
COLUMN_NAME | DATE_TYPE
___________________________________________________
UMOWA | VARCHAR2(30)
RODZ_LEAS | VARCHAR2(1)
KTH | NUMBER(10)
SKRÓT | VARCHAR2(50)
NAZWA | VARCHAR2(240)
AMORTYZ | NUMBER(10,6)
WALUTA | VARCHAR2(3)
WARTOSC_UMW | NUMBER
LICZBA_RAT | NUMBER
WK | NUMBER
WK% | NUMBER
Rodzaj stopy baz.| VARCHAR2(2000)
Wart.stopy baz. | NUMBER
REFI | NUMBER
RA_NR_RATY | NUMBER(10)
RA_TYP | VARCHAR2(10)
RA_DATA_SPLATY | DATE
RA_KWOTA_NETTO | NUMBER(12,2)
RA_KAPITAL_POZOSTALY | NUMBER(12,2)
Procedure in SQL Server - it works - I get the data from Oracle.
CREATE PROCEDURE [egeria].[ContractData_P] (#ContractNumberPar varchar(20))
AS
EXECUTE(
'Select
Umowa ContractNumber
, Rodz_leas TypeOfLeasing
, Kth CodeClient
, skrót Short
, Nazwa NameOfClient
, amortyz Amortization
, Waluta Currency
, Wartosc_Umw ContractValue
, Liczba_rat NumberOfInstallments
, WK FinalValue
, "WK%" FinalValuePercent
, "Rodzaj stopy baz." TypeOfBaseRate
, "Wart.stopy baz." ValueOfBaseRate
, REFI
, ra_nr_raty InstallmentNumber
, ra_typ Type
, ra_data_splaty MaturityDate
, ra_kwota_netto NetAmount
, ra_kapital_pozostaly CapitalRemaining
from RAPADM.XLS_SKROCENIA_UMOW_V
where UMOWA = ?'
, #ContractNumberPar) AT EF_EG5PROD
GO
Model
public class ContractData
{
public string ContractNumber { get; }
public string TypeOfLeasing { get; }
public int CodeClient { get; }
public string Short { get; }
public string NameOfClient { get; }
public decimal Amortization { get; }
public string Currency { get; }
public decimal ContractValue { get; }
public decimal NumberOfInstallments { get; }
public decimal FinalValue { get; }
public decimal FinalValuePercent { get; }
public string TypeOfBaseRate { get; }
public decimal ValueOfBaseRate { get; }
public decimal REFI { get; }
public decimal InstallmentNumber { get; }
public string Type { get; }
public DateTime MaturityDate { get; }
public decimal NetAmount { get; }
public decimal CapitalRemaining { get; }
}
Context
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
public virtual DbSet<ContractData> ContractData { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ContractData>().HasNoKey();
}
}
ContractDataService -- HERE I HAVE ERROR
private readonly AppDbContext _context;
public ContractDataService(AppDbContext context)
{
_context = context;
}
public async Task<IEnumerable<ContractData>> ExecAsync(string contractNumberPar)
{
var data = _context.ContractData.FromSqlRaw("EXECUTE [egeria].[ContractData_P] #ContractNumberPar", contractNumberPar).AsEnumerable();
return data;
}
Error:
system.InvalidOperationException: Sequence contains no elements at
System.Linq.ThrowHelper.ThrowNoElementsException() at
System.Linq.Enumerable.Max(IEnumerable`1 source) at
Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitBinary(BinaryExpression
binaryExpression) at
System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at
System.Dynamic.Utils.ExpressionVisitorUtils.VisitBlockExpressions(ExpressionVisitor
visitor, BlockExpression block) at
System.Linq.Expressions.ExpressionVisitor.VisitBlock(BlockExpression
node) at
System.Linq.Expressions.BlockExpression.Accept(ExpressionVisitor
visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression
node) at
Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.VisitExtension(Expression
extensionExpression) at
System.Linq.Expressions.Expression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at
Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ProcessShaper(Expression
shaperExpression, RelationalCommandCache& relationalCommandCache,
LambdaExpression& relatedDataLoaders, Int32& collectionId) at
Does anyone have an idea how to do this? Should I go another way?
Please check if what I am doing has any sense, or is it not better to go a better way?

EF Core cannot create projection expression because all properties of ContractNumber are readonly. Add setters to solve your issue:
public class ContractData
{
public string ContractNumber { get; set; }
public string TypeOfLeasing { get; set; }
public int CodeClient { get; set; }
public string Short { get; set; }
public string NameOfClient { get; set; }
public decimal Amortization { get; set; }
public string Currency { get; set; }
public decimal ContractValue { get; set; }
public decimal NumberOfInstallments { get; set; }
public decimal FinalValue { get; set; }
public decimal FinalValuePercent { get; set; }
public string TypeOfBaseRate { get; set; }
public decimal ValueOfBaseRate { get; set; }
public decimal REFI { get; set; }
public decimal InstallmentNumber { get; set; }
public string Type { get; set; }
public DateTime MaturityDate { get; set; }
public decimal NetAmount { get; set; }
public decimal CapitalRemaining { get; set; }
}

Related

How to tell which table column is causing an invalid cast exception?

Using EF Core 3.1, I'm trying to get a table from the database (SQL Server) using the following code:
query = dbContext.Set<Entity>().ToList();
The code is working for other tables but fails on a specific table with the following exception:
System.InvalidCastException: Unable to cast object of type 'System.Byte' to type 'System.Int32'.
at Microsoft.Data.SqlClient.SqlBuffer.get_Int32()
at Microsoft.Data.SqlClient.SqlDataReader.GetInt32(Int32 i)
at lambda_method(Closure , QueryContext , DbDataReader , ResultContext , Int32[] , ResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable`1.Enumerator.MoveNext()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
Using a breakpoint in a try-catch doesn't help as the inner exception is null. How can I tell which table column is causing the cast exception?
Model code:
[Table("Plugin")]
public partial class Plugin
{
public Plugin()
{
SetAPlugins = new HashSet<SetProfile>();
SetBplugins = new HashSet<SetProfile>();
SetBPlugins = new HashSet<SetProfile>();
SetBPlugins = new HashSet<SetProfile>();
SetBPlugins = new HashSet<SetProfile>();
}
[Key]
[Column("ID")]
public Guid ID { get; set; }
public int Serial { get; set; }
[Column(TypeName = "datetime")]
public DateTime? DateCreated { get; set; }
[Column(TypeName = "datetime")]
public DateTime? DateModified { get; set; }
public ObjectStatus ObjectStatus { get; set; }
[Required]
public byte[] Timestamp { get; set; }
public PluginType Type { get; set; }
[StringLength(64)]
public string Name { get; set; }
[StringLength(512)]
public string ProcessorAssembly { get; set; }
[StringLength(512)]
public string ProcessorClass { get; set; }
[StringLength(512)]
public string AdminAssembly { get; set; }
[StringLength(512)]
public string AdminClass { get; set; }
[StringLength(32)]
public string ConfigName { get; set; }
public ProfileType SubType { get; set; }
[StringLength(256)]
public string ContainerType { get; set; }
[StringLength(256)]
public string SupportedFeatures { get; set; }
[InverseProperty(nameof(SetProfile.SetAPlugin))]
public virtual ICollection<SetProfile> SetAPlugins { get; set; }
[InverseProperty(nameof(SetProfile.SetBplugin))]
public virtual ICollection<SetProfile> SetBPlugins { get; set; }
[InverseProperty(nameof(SetProfile.SetCPlugin))]
public virtual ICollection<SetProfile> SetCPlugins { get; set; }
[InverseProperty(nameof(SetProfile.SetDPlugin))]
public virtual ICollection<SetProfile> SetDPlugins { get; set; }
[InverseProperty(nameof(SetProfile.SetEPlugin))]
public virtual ICollection<SetProfile> SetEPlugins { get; set; }
}
I've attached a screenshot of the DB columns from SSMS.
The problem is
public ObjectStatus ObjectStatus { get; set; }
& The enum must be created as follows:
public enum ObjectStatus : byte
{
//List of values
}
The problem was that the SQL type is tinyint which is a Byte in code and which cannot be implicitly converted to enum. I used the following code to solve this:
[Column("ObjectStatus")]
public Byte objectStatus { get; set; }
[NotMapped]
public ObjectStatus ObjectStatus
{
get
{
if (objectStatus > 0)
return (ObjectStatus)objectStatus;
else
return ObjectStatus.Active;
}
set
{
objectStatus = (Byte)value;
}
}
You are mapping a property as int which should be a byte and only have one property mapped as int, which is Serial, so that should be the one.

Linq simple query returns unexpected results

I have configured my connection to DB as follows:
Web.config
<add name="MyContext" providerName="System.Data.SqlClient" connectionString="Data Source=MyServer;Initial Catalog=MyDB;User id=MyId;Password=MyPassword; MultipleActiveResultSets=true" />
Then I have my class to create context in order to access Database
public class MyContext: DbContext
{
public MyContext() : base("MyContext")
{
Database.SetInitializer<Models.MyContext>(null);
}
public DbSet<MyModel> MyTable { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
}
Then I have my DB with table 'MyTable', which is a history table, so every day at 6:00 I am inserting data from another table, finally I will have results like this
Id | Date
-----------------------------
1 | 2018-05-30 16:01:00.332
1 | 2018-05-31 14:21:03.456
1 | 2018-06-01 11:45:01.316
2 | 2018-05-30 21:44:00.544
2 | 2018-05-31 22:45:00.987
2 | 2018-06-01 23:46:00.769
So now in MyController.cs
public IQueryable<MyModel> GetData(string Id)
{
var result = MyContext.MyTable.AsQueryable();
return result.Where(w => w.Id == Id).toList();
}
I am trying to return all rows for Id = 1, on debugging when I set a breakpoint in the return statement, it returns the same row, for every record.
Id | Date
-----------------------------
1 | 2018-05-30 16:01:00.332
1 | 2018-05-30 16:01:00.332
1 | 2018-05-30 16:01:00.332
Edit: I add MyModel class as you requested
public class MyModel
{
[Index(IsUnique = false)]
public int Id { get; set; }
public DateTime Date{ get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
public string Field3 { get; set; }
public string Field4 { get; set; }
public string Field5 { get; set; }
public string Field6 { get; set; }
public string Field7 { get; set; }
public DateTime? Field8 { get; set; }
public string Field9 { get; set; }
public string Field10 { get; set; }
public string Field11 { get; set; }
public string Field12 { get; set; }
public string Field13 { get; set; }
public string Field14 { get; set; }
public string Field15 { get; set; }
public string Field16 { get; set; }
public string Field17 { get; set; }
public string Field18 { get; set; }
public string Field19 { get; set; }
public int? Field20 { get; set; }
public string Field21 { get; set; }
public int? Field22 { get; set; }
public int? Field23 { get; set; }
public int? Field24 { get; set; }
public string Field25 { get; set; }
public string Field26 { get; set; }
public string Field27 { get; set; }
public int Field28 { get; set; }
public string Field29 { get; set; }
public string Field30 { get; set; }
public string Field31 { get; set; }
public string Field32 { get; set; }
public string Field33 { get; set; }
public DateTime? Field34 { get; set; }
}
Can you help me to figure out what's going on?
Thanks.
[Index(IsUnique = false)]
public int Id { get; set; }
This does not prevent Id from being the Primary Key. If it did you would have seen another error, EF demands a PK on your classes.
You have only added an extra Index on the Id column. Not removed the PK constraint.
So our first suspicions appear to be right, you load a bunch of records with duplicate PK values in memory. When you try SaveChanges() you will get an error or lose data.
A simple fix would look like
public class MyModel
{
[Key]
public int ModelId { get; set; } // auto filled, ignore where you don't need it
//[Index(IsUnique = false)] -- not needed
public int Id { get; set; }
public DateTime Date{ get; set; }
...

The binary operator Equal is not defined for the types 'System.DateTime' and 'System.Object'. --Comparing Datetime linq

I am having and issue comparing two date range in linq. My view throws an exception
The binary operator Equal is not defined for the types
'System.DateTime' and 'System.Object'. Please how do i fix this ?
Any help would be appreciated.
public ViewResult List(SearchTerms search, int page = 1)
{
(from posts in repository.JobPosts
orderby posts.PostDate descending
select new
{
Id = posts.Id,
......
})
.Where(x => ((search.PostedDateFrom.CompareTo(DbFunctions.TruncateTime(DateTime.Now.Date)) != 0
|| (search.PostedDateTo.CompareTo(DbFunctions.TruncateTime(DateTime.Now.Date)) != 0)) ?
x.PostDate >= search.PostedDateTo && x.PostDate <= search.PostedDateTo : x.PostDate !=null)
)).....
}
My searchterm model.
public class SearchTerms
{
public string searchText { get; set; }
public string JobFunction { get; set; }
public string JobIndustry { get; set; }
public string jobType { get; set; }
public string JobLevel { get; set; }
public DateTime PostedDateFrom { get; set; }
public DateTime PostedDateTo { get; set; }
public decimal MinSalary { get; set; }
public string JobRegion { get; set; }
}
Any help would be appreciated .
Update
below is my JobPost Model.
public class JobPost
{
public long Id { get; set; }
public string Post { get; set; }
public DateTime PostDate { get; set; }
public long UserId { get; set; }
public string Region { get; set; }
public string JobType { get; set; }
public string PostTitle { get; set; }
public string Industry { get; set; }
public string JobFunction { get; set; }
public string JobLevel { get; set; }
public decimal Salary { get; set; }
public int Experience { get; set; }
public DateTime JobExpiryDate { get; set; }
public bool Active { get; set; }
}
I think your problem is that DateTime.Compare to takes an argument of type DateTIme, but TruncateTime returns a nullable DateTime. I think you have to cast the result from TruncateTime.

Calculate sum of multiple items in array in C#

I'm trying to get a sum for items I have within a class. To explain you better, I'm having cart object for which I can calculate the total sum with this method:
public decimal ComputeTotalValue()
{
return itemCollection.Sum(e => e.Item.Price*e.Quantity);
}
The item object in our case is this one:
public class CartItem
{
public RestItem Item { get; set; }
public int Quantity { get; set; }
}
Now the RestItem class has these properties:
public class RestItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int InStockNow { get; set; }
public int Order { get; set; }
public decimal Price { get; set; }
public bool HasImage { get; set; }
public bool HasModifiers { get; set; }
public string PLU { get; set; }
public int CategoryId { get; set; }
public byte[] ImageArray { get; set; }
public IEnumerable<ModifierOption> Modifiers { get; set; }
}
The last property, Modifiers is new property which I included today and this is the content:
public class ModifierOption
{
public string ID { get; set; }
public decimal Price { get; set; }
}
What I want to achieve is when the ComputeTotalValue is called, If there are ModifierOption fields as well, I want to calculate the sum of those fields as well and include the result in the total sum.
You can just add price of modifiers to price of your item, can't you?
public decimal ComputeTotalValue()
{
return itemCollection.Sum(e => (e.Item.Price + e.Item.Modifiers.Sum(m=>m.Price))*e.Quantity);
}
Do it like this:
public class RestItem
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int InStockNow { get; set; }
public int Order { get; set; }
public decimal Price { get; set; }
public bool HasImage { get; set; }
public bool HasModifiers { get; set; }
public string PLU { get; set; }
public int CategoryId { get; set; }
public byte[] ImageArray { get; set; }
public IEnumerable<ModifierOption> Modifiers { get; set; }
public decimal ComputeTotalPrice() {
return (this.Modifiers?.Sum(x => x.Price) ?? 0) + Price;
}
}
public decimal ComputeTotalPrice(){
return itemCollection?.Sum(x => x.ComputeTotalPrice()) ?? 0;
}

LINQ Query in Junction Table

I have a table that looks like this :-
CategoryId | QuestionId
-----------------------
1 | 2
1 | 3
3 | 2
4 | 3
I need to pull out all of the Questions that are not in use by a specific category. so for eg, CategoryID = 1.
The result should be that there are no questions to display.
Anyone know the best way to do this? so far i've not got anywhere with it.
EDIT **
public partial class FAQ
{
public FAQ()
{
this.FAQCategoriesFAQs = new HashSet<FAQCategoriesFAQ>();
}
public int Id { get; set; }
public string Question { get; set; }
public string Answer { get; set; }
public bool IsVisible { get; set; }
public Nullable<System.DateTime> DateLastUpdated { get; set; }
public System.DateTime DateCreated { get; set; }
public bool IsDeleted { get; set; }
public virtual ICollection<FAQCategoriesFAQ> FAQCategoriesFAQs { get; set; }
}
public partial class FAQCategory
{
public FAQCategory()
{
this.FAQCategoriesFAQs = new HashSet<FAQCategoriesFAQ>();
}
public int Id { get; set; }
public string Name { get; set; }
public int DomainId { get; set; }
public Nullable<System.DateTime> DateLastUpdated { get; set; }
public System.DateTime DateCreated { get; set; }
public bool IsDeleted { get; set; }
public int SortOrder { get; set; }
public virtual Domain Domain { get; set; }
public virtual ICollection<FAQCategoriesFAQ> FAQCategoriesFAQs { get; set; }
}
public partial class FAQCategoriesFAQ
{
public int FAQCategoryId { get; set; }
public int FAQId { get; set; }
public int SortOrder { get; set; }
public virtual FAQCategory FAQCategory { get; set; }
public virtual FAQ FAQ { get; set; }
}
If you have navigation property for categories in Question entity:
db.Questions.Where(q => !q.Categories.Any(c => c.Id == id))
UPDATE Thus your junction table differs a little bit from your original question :)
db.FAQs.Where(q => !q.FAQCategoriesFAQs.Any(qc => qc.FAQCategoryId == id))

Categories

Resources