I have 2 entities:
[TableName("is_userrole")]
public class UserRole
{
[MapField("id"), PrimaryKey, Identity,
public Guid id;
[NotNull]
public string Name;
}
[TableName("is_users")]
public class User
{
[MapField("id"), PrimaryKey, Identity,
NonUpdatable]
public Guid Id;
[NotNull]
public string Name;
[NotNull]
public string Login;
[NotNull]
public string Password;
public Guid UserRole_Id;
[Association(ThisKey = "UserRole_Id", OtherKey = "Id",
CanBeNull = false)]
public UserRole UserRole;
}
and stored procedure on sql server which gets data from query
[Select u., r. from is_users u
inner join is_userrole r on u.userrole_id = r.id]
if i use linq query like
var query = from u in db.User
select new
{
u.Id,
u.Login,
u.Password,
u.UserRole_Id,
u.UserRole
};
Associations filling, but if I execute procedure only parent object(i.e. user) filled.
How in bltoolkit.net associations with stored procedures made?
Or it can be only manually realised?
Thanks.
Ok so I don't have any experience with this but I quickly looked at the unit-tests and it looks like MapResultSet could help you
the unit test are here -> UnitTests\CS\Mapping\ResultSetTest.cs
AssosiationAttribute is used only for Linq expressions.
Point to know: BLT does NO "hidden" actions, for ex. if you will change your linq code as: db.User.ToList() you'll see that UserProperty is not filled. In your sample filling is done because you have said to done it in select clausue, and Association is used only to build proper 'INNER JOIN' in SQL.
Related
This might seem silly, but it's irritating.I'm using C# and cosmosdb sdk.
I have a document in db, lets say employee, and a corresponding Employee-class in my code.
employee
{
id: "123",
firstName : "Hans",
age : 23
}
and when updating the Employee-class in code to
public class Employee
{
public string Id{get;set}
public string FirstName{get;set}
public string LastName{get;set} // new
public int Age{get;set}
public Dictionary<string, object> OtherProperties {get;set} // also new
}
...then reading an existing document in code (GetById) and Upserting in again my document looks like this
employee
{
otherProperties : null,
id: "123"
firstName : "Hans",
lastName : null,
age : 23
}
What irritates me is that the otherProperties-property is now the first one. lastName (which was also added) happens to be exactly where it is in the class. Can I fix this somehow?
I have tested to have the property in another order in the class and also tried to change datatype to string, no difference.
Could you explain from a functional side what problem the order of properties generates?
You can decorate the class using the Newtonsoft.Json's Order on the JsonProperty: https://www.newtonsoft.com/json/help/html/JsonPropertyOrder.htm but aside from a cosmetic result, there isn't much of a functional difference.
Something like:
public class Employee
{
[JsonProperty(Order = 1)]
public string Id{get;set}
[JsonProperty(Order = 2)]
public string FirstName{get;set}
[JsonProperty(Order = 3)]
public string LastName{get;set}
[JsonProperty(Order = 4)]
public int Age{get;set}
[JsonProperty(Order = 5)]
public Dictionary<string, object> OtherProperties {get;set}
}
I have a class mapped to an SQL table and can perform a Linq query ok. I need to access some of the information in Products and modify data such as Price before returning as a JSon object.
The problem is a i cant access any of the information in Products. Could someone please advise how i could achieve this?
Class:
<Table(Name:="dbo.VXPartsData")>
Public Class VXPartsData
<Key()>
Public Property PartNo() As String
Public Property CustPart() As String
Public Property ShortDesc() As String
Public Property Part() As String
Public Property Price() As Decimal?
Public Property DiscCode() As String
Public Property Kit() As Boolean
Public Property VXCODE() As String
End Class
Linq query:
Dim Products = DB.VXPartsData.Where(Function(e) e.PartNo = pair.Key).ToList()
I'm using EF Core which I believe is also known as EF 7? Anyways, I have a stored procedure that returns custom results that will not identify with any specific table. How am I supposed to access those results and how should I call the sql command?
Normally we have to use .FromSql but that is only available on entities, eg. _context.User.FromSql(). I don't have an entity for it.
So I tried building a dbset/entity for the results, but again, there is no associated table, and there is also no "Key". How am I supposed to parse the data then of the custom results?
You can create a fake entity for the result of your stored procedure. You can set any property as the Key, even if in the results of the stored procedure the key values are not unique.
For example if you have a table like the following :
CREATE TABLE [dbo].[banana_hoard]
(
[id] INT NOT NULL PRIMARY KEY IDENTITY (1,1),
[owner] NVARCHAR(64) NOT NULL,
[bananas] BIGINT NOT NULL
)
You can have a query that does not return the row id like this :
public class Program
{
public static void Main(string[] args)
{
using (var db = new MonkeyDbContext())
{
var sp_results = db.search.FromSql(#"execute <YOUR_STORED_PROC>");
str_result = String.Join("\n", sp_results.Select(a => JsonConvert.SerializeObject(a) ));
Console.WriteLine("stored proc result :\n" + str_result);
}
}
}
public class MonkeyDbContext : DbContext
{
public DbSet<StoredProcRow> search { get; set; }
protected override void OnConfiguring (DbContextOptionsBuilder builder)
{
builder.UseSqlServer(#"Server=(localdb)\monkey_db;Database=monkey_db;Trusted_Connection=True;");
}
}
public class StoredProcRow
{
[Key]
public string Owner { get; set; }
public long Bananas { get; set; }
}
I have 3 tables which contains same set of columns. Do i need to create 3 entities for all the DB tables? Is there a way to avoid creating 3 entities and have only one in ServiceStack?
Yes there is one way of doing it like below
List<EntityA> list = db.SqlList<EntityA>("SELECT COL_A,COL_B FROM TableA");
Entity without Alias on Class
public class EntityA
{
[Alias("COL_A")]
public string ColumnA { get; set; }
[Alias("COL_B")]
public string ColumnB { get; set; }
}
in this way i can change the table name(TableA/TableB/TableC) provided in the Query
but I want something like injecting / passing the alias while retrieving the results from the database. I am not sure if this is possible with service stack
Edited
Let me rephrase the question Instead of returning differenct objects like EntityTableA/EntityTableB/EntityTableC as Result i want
return db.Select<GenericEntity>(w => w.OrderBy(o => o.ColumnA));
the GenericEntity can be any tables result
You can just use inheritance to reduce boilerplate:
public class EntityBase
{
[Alias("COL_A")]
public string ColumnA { get; set; }
[Alias("COL_B")]
public string ColumnB { get; set; }
}
Then inherit properties from the shared entity, e.g:
public class TableA : EntityBase {}
public class TableB : EntityBase {}
Then query it as normal:
var results = db.Select<TableA>(q => ColumnA == "A");
Otherwise yeah the using any of the raw SQL API's will work as well.
Modifying SqlExpression
You can also override the SqlExpression FromExpression to include your own table, e.g:
var q = db.From<GenericEntity>().OrderBy(o => o.ColumnA);
q.From("TableA");
List<GenericEntity> results = db.Select(q);
This will change the SQL to SELECT from TableA instead.
I have two tables CatalogueBase and CatalogueCopydetails now i am using Hibernate search for CatalogueBase table but i wanted to search even in CatalogueCopydetails table. This two tables are related with #ManyToOne (i.e CatalogueCopydetails using CatalogueBase id as foreign key), hear for one entry of CatalogueBase their will be 'n' numbers of CatalogueCopydetails
CatalogueBase POJO Class
#Indexed
#JsonAutoDetect
#Entity
#Table(name="catalogueBase")
public class CatalogueBase extends BaseObject implements Serializable {
private Long id;
......
#Id
#GeneratedValue
#Column(name="id")
#Field(index = Index.YES, analyze = Analyze.YES, store = Store.YES)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
....
CatalogueCopydetails POJO Class
#JsonAutoDetect
#Entity
#Table(name="cataloguecopydetails")
public class CatalogueCopyDetails extends BaseObject implements Serializable {
private CatalogueBase catalogueBase;
......
#ManyToOne
#JoinColumn(name="cataloguebaseid" , insertable=true, updatable=true,nullable=true)
public CatalogueBase getCatalogueBase() {
return catalogueBase;
}
public void setCatalogueBase(CatalogueBase catalogueBase) {
this.catalogueBase = catalogueBase;
}
......
at least how can i use #IndexedEmbedded for this scenario (i don't think i can use #IndexedEmbedded because CatalogueBase have no relation to CatalogueCopyDetails like OneToOne or OneToMany etc only CatalogueCopyDetails references CatalogueBase )
how can i do this..?, any help will be appreciated, Thanks.
The easiest way would of course be to make the relation bidirectional. Is there a good reason why you don't want to do that? The other thing you could do is to add #Indexed to CatalogueCopyDetails as well and use #IndexedEmbedded on CatalogueBase. You could then write a query using the CatalogueCopyDetails index. Whether this works will depend on your use case and what you actually want as result of query.