my query
/API/Json/GetJson?Desc=test1
I get all records not just the test1 records
[Route("/API/Json/GetJson", "GET")]
public class GetJson : QueryDb<JsonModel>
{
public int? Id { get; set; }
public int? RefId { get; set; }
public int? SecondRefId { get; set; }
public int? ThirdRefId { get; set; }
public int? FourthRefId { get; set; }
public string Name { get; set; }
public string JSON { get; set; }
public string JsonType { get; set; }
public string Desc { get; set; }
public int? AuditId { get; set; }
}
public class JsonModel
{
[AutoIncrement]
[PrimaryKey]
[IgnoreOnUpdate]
public int Id { get; set; }
/// <summary>
/// Other tables the this data is relevant to
/// </summary>
public int? RefId { get; set; }
public int? SecondRefId { get; set; }
public int? ThirdRefId { get; set; }
public int? FourthRefId { get; set; }
/// <summary>
/// name that is displayed to users
/// </summary>
[Required]
public string Name { get; set; }
public string JSON { get; set; }
/// <summary>
/// Tells what data type the JSON is storing
/// </summary>
[Required]
public string JsonType { get; set; }
public string Desc { get; set; }
public int AuditId { get; set; }
public DateTime AuditStamp { get; set; } = DateTime.UtcNow;
}
also my return data has extra fields. Starting at Skip
{
"id": 4,
"refId": 9,
"secondRefId": 3,
"thirdRefId": 100,
"fourthRefId": null,
"name": "test",
"json": "JSON STRING DATA",
"jsonType": "test",
"desc": "test3",
"auditId": 0,
**"skip": null,
"take": null,
"orderBy": null,
"orderByDesc": null,
"include": null,
"fields": null,
"meta": null**
},
I updated my model to nullables and its is till returing all records. My seed data and I am using SS 5.6.0
WireUpService<IntegrationService>();
using (var db = HostContext.Resolve<IDbConnectionFactory>().Open())
{
string JSON = " \"Columns\": [\r\n {\r\n \"CompanyName\": [\r\n {\r\n \"name\": \"Company Name\",\r\n \"Visible\": \"True\",\r\n \"Sort\": \"U,A,Z[Unsorted, A-Z, Z-A]\",\r\n \"Filter\": \"Test Company\"\r\n }\r\n ],\r\n \"ParentCompnay\": [\r\n {\r\n \"name\": \"Company Name\",\r\n \"Visible\": \"True\",\r\n \"Sort\": \"U,A,Z[Unsorted, A-Z, Z-A]\",\r\n \"Filter\": \"Test Company\"\r\n }\r\n ]\r\n }";
db.DropAndCreateTable<JsonModel>();
db.Insert(new JsonModel { Desc = "test",Name = "test",JsonType = "test", JSON = JSON,RefId = 10,SecondRefId = 3, AuditId = 0, AuditStamp = DateTime.Now });
db.Insert(new JsonModel { Desc = "test1", Name = "test", JsonType = "test", JSON = JSON, RefId = 10, SecondRefId = 3, AuditId = 0, AuditStamp = DateTime.Now });
db.Insert(new JsonModel { Desc = "test2", Name = "test", JsonType = "test", JSON = JSON, RefId = 5, SecondRefId = 3, AuditId = 0, AuditStamp = DateTime.Now });
db.Insert(new JsonModel { Desc = "test3", Name = "test", JsonType = "test", JSON = JSON, RefId = 9, SecondRefId = 3,ThirdRefId = 100, AuditId = 0, AuditStamp = DateTime.Now });
}
I wasn't able to reproduce this issue using the classes provided, which I've seeded with test data that matches the query and non-matching test data that you've included in your JSON response:
db.CreateTable<JsonModel>();
db.Insert(new JsonModel { RefId = 1, SecondRefId = 1, ThirdRefId = 111, Name = "test1", Desc = "test1", JsonType = "test", JSON = "TEST1"});
db.Insert(new JsonModel { RefId = 9, SecondRefId = 3, ThirdRefId = 100, Name = "test1", Desc = "test3", JsonType = "test", JSON = "JSON STRING DATA"});
There is an issue with your GetJson model where you've specified Id and AuditId as non-nullable int properties which if not specified are populated in your GetJson Request DTO as 0 (default int).
If you're going to include required value types on your GetJson AutoQuery Service you should always be providing values for them otherwise change them into int? so they're not added to the query filter when they're not specified, e.g:
public class GetJson : QueryDb<JsonModel>
{
public int? Id { get; set; }
public int? AuditId { get; set; }
}
After doing this, it works as expected where I can query the Auto Query Service using your specified query, i.e:
var url = baseUrl.CombineWith("/API/Json/GetJson").AddQueryParam("Desc", "test1");
var json = url.GetJsonFromUrl();
json.Print();
Which works as expected returning the matching result in a QueryResponse<T> DTO, i.e:
{"Offset":0,"Total":0,"Results":[{"Id":1,"RefId":1,"SecondRefId":1,"ThirdRefId":111,"Name":"test1","JSON":"TEST1","JsonType":"test","Desc":"test1","AuditId":0,"AuditStamp":"\/Date(1577190306230-0000)\/"}],"Meta":{}}
Related
public class LoadTagMapModel
{
public string TAG { get; set; }
public string LOAD_CODE { get; set; }
public string SPEC_DATA { get; set; }
public string TAG_ID { get; set; }
public decimal? REF_VAL { get; set; }
public decimal? USL_VAL { get; set; }
public decimal? LSL_VAL { get; set; }
public int ORDER_NO { get; set; }
}
LoadTagMapModel model = new LoadTagMapModel
{
TAG = txtTag.Text,
LOAD_CODE = txtLOAD_CODE.Text,
TAG_ID = bteTAG_ID.Text,
SPEC_DATA = txtSPEC_DATA.Text,
REF_VAL = txtREF_VAL.Text == "" ? (decimal?)null : txtREF_VAL.Text.ToDecimal(),
USL_VAL = txtUSL_VAL.Text == "" ? (decimal?)null : txtUSL_VAL.Text.ToDecimal(),
LSL_VAL = txtLSL_VAL.Text == "" ? (decimal?)null : txtLSL_VAL.Text.ToDecimal(),
ORDER_NO = txtORDER_NO.Text.ToInt()
};
bool result = this.SaveData(model);
if (result)
{
this.MessageBoxShow("Saved.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
Search_Master();
return true;
}
I set types REF_VAL, USL_VAL, LSL_VAL to decimal?.
But if those value is null then in database it has to be DBNull value.
I want to these value can set DBNull value for decimal?.
Originally decimal couldn't allow null value but (decimal?)null is available.
In database, it has to be DBNull value type.
Could you help me?
I have 3 entities:
[CompositeIndex(nameof(Url), nameof(TargetDomainRecordId), nameof(UserAuthCustomId), Unique = true)]
public class WatchedUrlRecord
{
[AutoIncrement]
public long Id { get; set; }
public string Url { get; set; }
public string Provider { get; set; }
public string DomainKey { get; set; }
public WatchedUrlScanStatus WatchedUrlScanStatus { get; set; }
public bool NoFollow { get; set; }
public HttpStatusCode HttpStatusCode { get; set; }
public DateTime? LastScanTime { get; set; }
public WatchedUrlScanResult LastScanData { get; set; }
public string Anchors { get; set; }
public int? OutboundLinks { get; set; }
[ForeignKey(typeof(TargetDomainRecord), OnDelete = "CASCADE")]
public long TargetDomainRecordId { get; set; }
[ForeignKey(typeof(UserAuthCustom), OnDelete = "CASCADE")]
public long UserAuthCustomId { get; set; }
}
[CompositeIndex(nameof(Url), nameof(TargetDomainRecordId), nameof(UserAuthCustomId), Unique = true)]
public class WatchedUrlQueue
{
[PrimaryKey]
public long WatchedUrlRecordId { get; set; }
[Index]
public string Url { get; set; }
[Index]
public string DomainKey { get; set; }
[Index]
public long TargetDomainRecordId { get; set; }
public string TargetDomainKey { get; set; }
[Index]
public DateTime CreateDate { get; set; } = DateTime.UtcNow;
public int Tries { get; set; }
[Index]
public DateTime? DeferUntil { get; set; }
[Index]
public long UserAuthCustomId { get; set; }
[Index]
public bool FirstScan { get; set; }
}
[CompositeIndex(nameof(Url), nameof(UserAuthCustomId), Unique = true)]
public class TargetDomainRecord
{
[AutoIncrement]
public long Id { get; set; }
public string Url { get; set; }
public string DomainKey { get; set; }
public DateTime CreateDate { get; set; } = DateTime.Now;
public DateTime? DeleteDate { get; set; }
public bool IsDeleted { get; set; }
public bool Active { get; set; } = true;
public DomainType DomainType { get; set; }
[ForeignKey(typeof(UserAuthCustom), OnDelete = "CASCADE")]
public long UserAuthCustomId { get; set; }
}
I am trying to insert queue objects based on IDs of WatchedUrlRecords so I came up with this query:
var q = db.From<WatchedUrlRecord>()
.Where(x => Sql.In(x.Id, ids))
.Join<TargetDomainRecord>((w, t) => w.TargetDomainRecordId == t.Id)
.Select<WatchedUrlRecord, TargetDomainRecord>((w, t) => new WatchedUrlQueue()
{
UserAuthCustomId = w.UserAuthCustomId,
DomainKey = w.DomainKey,
CreateDate = DateTime.UtcNow,
DeferUntil = null,
FirstScan = firstScan,
TargetDomainKey = t.DomainKey,
Tries = 0,
TargetDomainRecordId = w.TargetDomainRecordId,
Url = w.Url,
WatchedUrlRecordId = w.Id
});
var inserted = db.InsertIntoSelect<WatchedUrlQueue>(q, dbCmd => dbCmd.OnConflictIgnore());
This doesn't work and gives error:
variable 'w' of type 'Project.ServiceModel.WatchedUrl.Entities.WatchedUrlRecord' referenced from scope '', but it is not defined
If I try anonymous object like new {} instead of new WatchedUrlQueue then InsertIntoSelect() throws error:
'watched_url_record"."user_auth_custom_id' is not a property of 'WatchedUrlQueue'
I have looked in documentation and can see SelectMulti() method but I don't think that is suitable as it will involve me creating a tuple list to combine into the new object. The passed list can be quite large so I just want to send the correct SQL statement to PostgreSQL which would be along lines of:
insert into watched_url_queue (watched_url_record_id, url, domain_key, target_domain_record_id, target_domain_key, create_date, tries, defer_until, user_auth_custom_id)
select wur.id watched_url_record_id,
wur.url url,
wur.domain_key,
wur.target_domain_record_id,
tdr.domain_key,
'{DateTime.UtcNow:MM/dd/yyyy H:mm:ss zzz}' create_date,
0 tries,
null defer_until,
wur.user_auth_custom_id
from watched_url_record wur
join target_domain_record tdr on wur.target_domain_record_id = tdr.id
where wur.id in (323,3213123,312312,356456)
on conflict do nothing ;
I currently have a lot of similar type queries in my app and it is causing extra work maintaining them, would be really nice to be able to have them use fluent api without reducing performance. Is this possible?
Custom select expression can't be a typed projection (i.e. x => new MyType { ... }), i.e. you'd need to use an anonymous type expression (i.e. new { ... }) which captures your query's Custom SELECT Projection Expression.
You'll also need to put your JOIN expressions directly after FROM (as done in SQL) which tells OrmLite it needs to fully qualify subsequent column expressions like Id which would otherwise be ambiguous.
I've resolved an issue with field resolution of custom select expressions in this commit where your query should now work as expected:
var q = db.From<WatchedUrlRecord>()
.Join<TargetDomainRecord>((w, t) => w.TargetDomainRecordId == t.Id)
.Where(x => Sql.In(x.Id, ids))
.Select<WatchedUrlRecord, TargetDomainRecord>((w, t) => new {
UserAuthCustomId = w.UserAuthCustomId,
DomainKey = w.DomainKey,
CreateDate = DateTime.UtcNow,
DeferUntil = (DateTime?) null,
FirstScan = firstScan,
TargetDomainKey = t.DomainKey,
Tries = 0,
TargetDomainRecordId = w.TargetDomainRecordId,
Url = w.Url,
WatchedUrlRecordId = w.Id
});
var inserted = db.InsertIntoSelect<WatchedUrlQueue>(q, dbCmd=>dbCmd.OnConflictIgnore());
This change is available from v5.10.5 that's now available on MyGet.
here Is my Models ,here in my model PK is decorated with Key becoz in EF it must be . But as it is aslo available in base class. if I removed PK from Person it gives error as model has not assign a Key IN EF which is strange to me .
public class Person:TBase
{
[Key]
public long PK { get; set; }
public string NAME { get; set; }
public string ADDRESS { get; set; }
}
public class TBase: Base
{
public virtual long? FKTenant { get; set; }
public virtual bool IsDefault { get; set; }
}
public class Base
{
[Key]
public long PK { get; set; }
public virtual string GlobalID { get; set; }
}
and Controller
[EnableQuery]
public IHttpActionResult Get()
{
try
{
IQueryable<Person> result;
var result = DbContext.Persons.Where(x => x.FKTenant == context.FKTenant).ToList();
return Ok(result);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
i am getting response in postman is
"value": [
{
"#odata.etag": "W/\"bnVsbA==\"",
"PK": 1001,
"NAME": "VIVEK",
"ADDRESS": "DELHI",
"FKTenant":null,
"IsDefault ":null,
"GlobalID ":null
}]
But my Intention to get ouput response as below which should contain onlly name and address
"value": [
{
"#odata.etag": "W/\"bnVsbA==\"",
"NAME": "VIVEK",
"ADDRESS": "DELHI"
}]
Any guide will be appreciable.
You should use a ViewModel
write another class as ViewModel and when you want return object first map to new ViewModel then return it.
I want to ignore some properties from my Object during run time. The properties are decorated with data member attribute (Without data member attribute excludepropertyreferencces is working fine). Can you please provide some insight? Thanks
Question : HOW TO EXCLUDE PROPERTIES AT RUN TIME, IF THEY ARE DECORATE WITH DATAMEMBER ATTRIBUTE ?
ServiceStack , ExcludePropertyReferences
var model = new Model {
FirstName = "First Name",
LastName = "Last Name",
Children = new List<ModelChild>{
new ModelChild { ChildFirstName = "ChildFirstName 1", ChildLastName = "ChildLastName 1" },
new ModelChild { ChildFirstName = "ChildFirstName 2", ChildLastName = "ChildLastName 2" }
}
};
var model1 = new Model1 {
FirstName = "First Name",
LastName = "Last Name",
Children = new List<Model1Child>{
new Model1Child { ChildFirstName = "ChildFirstName 1", ChildLastName = "ChildLastName 1" },
new Model1Child { ChildFirstName = "ChildFirstName 2", ChildLastName = "ChildLastName 2" }
}
};
Console.WriteLine("Properties won't get ignored because the Model is decorated with Serialization Attributes");
using(MemoryStream stream = new MemoryStream())
using (var jsConfig = JsConfig.BeginScope()) {
jsConfig.ExcludeTypeInfo = true;
jsConfig.ExcludePropertyReferences = new [] { "Model.LastName", "ModelChild.ChildLastName" }.ToArray();
JsonSerializer.SerializeToStream(model, model.GetType(), stream);
LINQPad.Extensions.Dump(System.Text.Encoding.Default.GetString(stream.ToArray()));
}
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("Properties will get ignored because the Model is not decorated with Serialization Attributes");
using(MemoryStream stream = new MemoryStream())
using (var jsConfig = JsConfig.BeginScope()) {
jsConfig.ExcludeTypeInfo = true;
jsConfig.ExcludePropertyReferences = new [] { "Model1.LastName", "Model1Child.ChildLastName" }.ToArray();
JsonSerializer.SerializeToStream(model1, model1.GetType(), stream);
LINQPad.Extensions.Dump(System.Text.Encoding.Default.GetString(stream.ToArray()));
}
// Define other methods and classes here
[DataContract()]
public class Model {
[DataMember(Name = "first_name",EmitDefaultValue = false )]
public string FirstName { get; set; }
[DataMember(Name = "last_name")]
public string LastName { get; set; }
[DataMember(Name = "collections")]
public List<ModelChild> Children { get; set; }
}
[DataContract()]
public class ModelChild {
[DataMember(Name = "child_first_name")]
public string ChildFirstName { get; set; }
[DataMember(Name = "child_last_name")]
public string ChildLastName { get; set; }
}
public class Model1 {
public string FirstName { get; set; }
public string LastName { get; set; }
public List<Model1Child> Children { get; set; }
}
public class Model1Child {
public string ChildFirstName { get; set; }
public string ChildLastName { get; set; }
}
I'd like to be able to have the code below
[Route("/Incidents", "Get")]
public class GetViewConfig
{
public List<Filter> Filters { get; set; }
}
public class Filter
{
public string Property { get; set; }
public FilterType Type { get; set; }
public string Value { get; set; }
}
public enum FilterType
{
IsBetween,
Is,
IsNot
}
public class GetViewConfigResponse
{
public List<Filter> Filters { get; set; }
}
public class ViewConfigService : Service
{
public object Get(GetViewConfig request)
{
return null;
}
}
Show all the values for the FilterType on the metadata page. Is there a way to do this?
Not on the metadata pages, but you can view this using the Swagger API and the [ApiAllowableValues] attribute, e.g:
[Api("Service Description")]
[Route("/swagger/{Name}", "GET", Summary = #"GET Summary", Notes = "GET Notes")]
public class MyRequestDto
{
[ApiMember(Name="Name", Description = "Name Description",
ParameterType = "path", DataType = "string", IsRequired = true)]
[ApiAllowableValues("Name", typeof(Color))] //Enum
public string Name { get; set; }
}