Entity Framework Code First Text Store as Image in SQL - sql

I have a legacy SQL database that has a linked table to store specifications for order lines. The application designers use an image field in SQL to store the text as binary data. I mocked up an example below:
public class OrderLine
{
public int ID { get; set; }
public int OrderID { get; set; }
public int LineNo { get; set; }
public string Product { get; set; }
public decimal Quantity { get; set; }
public decimal UnitPrice { get; set; }
public string Status { get; set; }
}
public class OrderLineSpecifications
{
public int ID { get; set; }
public int OrderID { get; set; }
public int OrderLineNo { get; set; }
public Image Bits { get; set; } // <--- This Line
public int Bit_Length { get; set; }
}
SQL Table Definition
[ID] [int] IDENTITY(1,1) NOT NULL,
[OrderID] [varchar](15) NOT NULL,
[OrderLineNo] [smallint] NOT NULL,
[Bits] [image] NULL,
[Bit_Length] [int] NOT NULL
Currently I have to use SQL with
cast(cast(Bits as varbinary(max)) as varchar(max))
to extract the text and then perform the reverse to return it to the database. Is it possible to have the conversion done in EF? Perhaps at the property level { get; set;} ?

The solution was easier than I thought. I changed what was identified as an Image in SQL to a byte array (byte[]) and created a property (Specs) that processed the BITS values. Entity Framework was happy and it works in both directions. Surprisingly easy.
public virtual byte[] BITS { get; set; }
public virtual int BITS_LENGTH { get; set; }
[NotMapped]
public virtual string Specs
{
get
{
UTF8Encoding enc = new UTF8Encoding();
string str = enc.GetString(BITS);
return str;
}
set
{
UTF8Encoding encoding = new UTF8Encoding();
BITS = encoding.GetBytes(value);
}
}

Related

How to store value in variable joining two tables

I am still learning SQL, but as I got stuck in these doubt I wrote it here.
Actually I want print a table for list of details which hold a column for "Description". Now this data is retrieving from tblBillDetails. and in tblBillDetails there is no column or field of "Description. Now there is another field which is tblProduct here I have column "Name" & "Id".
So I want something like "Description = tblProduct.Name where tblBillDetails.FunctionId == tblProduct.Id
code--->
.cs file
public class BillDetail
{
public long Id { get; set; }
public long BillId { get; set; }
public int FunctionType { get; set; }
public long FunctionId { get; set; }
public long VatId { get; set; }
public int Quantity { get; set; }
public int Points { get; set; }
public decimal TotalValue { get; set; }
public decimal FreeValue { get; set; }
public DateTime SaleDateTime { get; set; }
public long BalanceId { get; set; }
public decimal RunningBalance { get; set; }
}
repositoy .cs file
public Task<BillDetail> SingleAsync(Guid shardKey, long BillDetailId)
{
return _billDetailDataAccess.SingleAsync(shardKey, BillDetailId);
}
DataAccess .cs file
public async Task<BillDetail> SingleAsync(Guid shardKey, long BillDetailId)
{
string sql = #"SELECT [Id]
,[TenantClientId]
,[BillId]
,[FunctionType]
,[FunctionId]
,[VatId]
,[Quantity]
,[Points]
,[TotalValue]
,[FreeValue]
,[SaleDateTime]
,[BalanceId]
,[RunningBalance]
,[Archived]
FROM [dbo].[tblBillDetail]
WHERE [tblBillDetail].[Id] = #BillDetailId
;";
await _context.OpenConnectionForKeyAsync(shardKey);
return await _context.Connection.QueryFirstOrDefaultAsync<BillDetail>(sql, new { BillDetailId });
}

EF Core Join using Include but ForeignKey is not Primary Key on the other table

I am trying to relate my Tables with ForeignKey and PrimaryKey on the other end. But now i will be using a ForeignKey which is not the primary for the said table. I was using [InverseProperty] but i think there's a bug with it since i've been looking around for hours already and all of them says the same thing about it.
Documents Table:
public class Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int DocumentId { get; set; }
public int ProjectId { get; set; }
public int DepartmentId { get; set; }
public int AuthorId { get; set; }
[NotMapped]
public virtual User Author { get; set; }
}
Users
public class User
{
[Key]
public int UserId { get; set; }
public int AuthUserId { get; set; }
public string DisplayName { get; set; }
[NotMapped]
[ForeignKey("AuthorId")]
public virtual Document Document { get; set; }
}
Context:
modelBuilder.Entity<User>(entity =>
{
entity.HasOne(u => u.Document)
.WithMany("AuthorId");
});
I am trying to use the solution they here, but no luck.
Any help would really be appreciated. Thanks!
But now i will be using a ForeignKey which is not the primary for the said table.
To do this you can use EF Core Alternate Keys feature. But first correct your model class set up as follows: (As you said a User will have multiple Document)
public class Document
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int DocumentId { get; set; }
public int ProjectId { get; set; }
public int DepartmentId { get; set; }
public int AuthorId { get; set; }
public User Author { get; set; }
}
public class User
{
[Key]
public int UserId { get; set; }
public int AuthUserId { get; set; }
public string DisplayName { get; set; }
public ICollection<Document> Documents { get; set; }
}
Then in the Fluent API configuration as follows:
modelBuilder.Entity<Document>()
.HasOne(p => p.Author)
.WithMany(b => b.Documents)
.HasForeignKey(p => p.AuthorId)
.HasPrincipalKey(b => b.AuthUserId); // <-- here you are specifying `AuthUserId` as `PrincipalKey` in the relation which is not primary key

ASP EF7 Set column value in migration

I want to move from autoincrement ids to composite primary keys. So, these two entities
public class SeasonTeam
{
public int SeasonTeamId { get; set; }
public int SeasonId { get; set; }
public int TeamId { get; set; }
}
public class GroupEntry
{
public int GroupEntryId { get; set; }
public int SeasonTeamId { get; set; }
public SeasonTeam SeasonTeam { get; set; }
}
will now look like this
public class SeasonTeam
{
public int SeasonId { get; set; }
public int TeamId { get; set; }
}
public class GroupEntry
{
public int GroupEntryId { get; set; }
public int SeasonId { get; set; }
public int TeamId { get; set; }
public SeasonTeam SeasonTeam { get; set; }
}
Visual Studio generated migration code, but it corrupts data.
migrationBuilder.AddColumn<int>(
name: "SeasonId",
table: "GroupEntry",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "TeamId",
table: "GroupEntry",
nullable: false,
defaultValue: 0);
migrationBuilder.DropForeignKey(name: "FK_GroupEntry_SeasonTeam_SeasonTeamId", table: "GroupEntry");
migrationBuilder.DropPrimaryKey(name: "PK_SeasonTeam", table: "SeasonTeam");
migrationBuilder.DropColumn(name: "SeasonTeamId", table: "SeasonTeam");
Default value 0 obviously won't work, I need ids from referenced SeasonTeam table, but I didn't find any examples. How can I set proper id values for a new composite key before I delete old primary key column?
You can't do this programmatically with EF's APIs, however, if you can write the SQL to move the values from one table to another, you can add a custom migration step after the Add column operations and before the drop column operations.
migrationBuilder.Sql(#"INSERT INTO ...(your SQL here)");
From the limited info in your question, I can't tell you what that SQL should be.

saving reference using ServiceStack ORMLite

I am using ORMLite as my ORM and I am using it with following structure which contains the foreign key relation ship:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
}
As we can see that Order contains the reference to the Item. In DB Order table has a foreign key called ItemId in the table and I have annotated that key in the design view with [Reference] attribute.
I am trying to save the Order with following code:
var order = new Order
{
Item = new Item
{
Id = 3,
Description = "Something"
},
ProUserId = "kunal#kunal.com",
Details = "fdfsdfsd"
};
Db.Save(order,references:true);
I was hoping that ORMLite would pick up the relationship and with ItemID in the Order table but it did not and it did throw following error instead:
Cannot insert the value NULL into column 'ItemId', table 'WebApp.dbo.Order'; column does not allow nulls. INSERT fails.
I tried changing my schema and addred OrderId column in my Item table with reference there and that works fine. But that is not the correct design. Should I make any changes in my code/schema to support this feature?
You still need to provide the foreign key that OrmLite can use to store the relationship, e.g. either on the Child/ForeignKey table:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public int OrderId { get; set; } //Parent Table PK
public string Description { get; set; }
}
Or for 1:1 relationships, can be on the Parent table, e.g:
public class Order
{
[AutoIncrement]
public int Id { get; set; }
[Reference]
public Item Item { get; set; }
public int ItemId { get; set; } //Child Table PK
public string ProUserId { get; set; }
public string Details { get; set; }
}
public class Item
{
[AutoIncrement]
public int Id { get; set; }
public string Description { get; set; }
}

Polymorphic nhibernate query with projection

Using a single table for a class hierarchy I would like to use a projection to flatten the hierarchy to present a list of results to the user.
Is there a way to do this using HQL or Criteria API without having to issue multiple separate queries or unions?
Classes
public class A {
public virtual long Id { get; set; }
}
public class B : A {
public virtual DateTime SomeDate { get; set; }
public virtual OtherEntity Other { get; set; }
}
public class C : A {
public virtual DateTime? SomeDate { get; set; }
public virtual string Description { get; set; }
}
public class D : A {
public virtual string Description { get; set; }
}
public class OtherEntity {
public virtual string Name { get; set; }
}
SQL Tables:
CREATE TABLE Items (
Id bigint NOT NULL PRIMARY KEY,
Kind char(1) NOT NULL,
SomeDate datetime NULL,
Description NULL
)
CREATE TABLE OtherEntity (
Id bigint NOT NULL PRIMARY KEY,
Name nvarchar(255) NOT NULL
)
Output projection:
public class ItemReport {
// From A.Id
public virtual long Id { get; set; }
// From B.SomeDate or C.SomeDate
public virtual DateTime? SomeDate { get; set; }
// From C.Description or D.Description
public virtual string Description { get; set; }
// From B.OtherEntity.Name
public virtual string OtherName { get; set; }
}