There is a well-known problem connected with creating custom visuals for Power BI Report Sever - you can't create multiple unrelated dataViewMappings. It means that every field you put inside Fields must be related.
There have been a long-lasting request from users to add this feature.
However, it looks like Microsoft hasn't implemented it yet.
https://github.com/Microsoft/PowerBI-visuals/issues/251
I found a workaround - you can combine all your different tables in one and chain with a tableName key.
For example, you have a table A:
value1|value2|tableName
1|2|tableA
3|4|tableA
and a table B:
value3|tableName
a|tableB
b|tableB
You create a tableC by using M function Table.Combine({tableA, tableB}) or other technique. As a result, it looks like this:
value1|value2|value3|tableName
1|2|null|tableA
3|4|null|tableA
null|null|a|tableB
null|null|b|tableB
Then, inside your custom visual you implement the following function which parses the input:
public parseOptionsToTables(options: VisualUpdateOptions) {
var i: number;
var j: number;
var cntRows: number;
var cntCols: number;
var nameTable: string;
var tempDict: {} = {};
var tempVal: any;
var colName: string;
var cats: any = options.dataViews[0].table;
this.tables = {};
cntCols = cats.columns.length;
cntRows = cats.rows.length;
for (i = 0; i < cntRows; i++) {
tempVal = null;
colName = null;
nameTable = null;
tempDict = {};
for (j = 0; j < cntCols; j++) {
//for every row - check the TableName column and add to dict
tempVal = cats.rows[i][j];
colName = cats.columns[j].displayName;
if (colName == 'tableName') {
nameTable = tempVal;
} else {
//add id not null
if (tempVal !== null) {
tempDict[colName] = tempVal;
}
}
}
//push to dict
this.tables[nameTable] = this.tables[nameTable] || [];
this.tables[nameTable].push(this.deepcopy(tempDict));
}
}
As a result, it creates a this.tables object with your tableA and tableB inside.
Although it helps to solve the main problem, I can't get out of feeling of creating crutches.
So, are there any other approaches to solve this problem more effeciently?
Related
Creating a WCF in VisualStudio 2017, I need to create a WebMethod that will return multiple rows from a SQL query. Here is the code that is not working...
code
[WebMethod]
public List<TABLE_NAME> GetAllLineInfoDetailes(string OrderNumberSM)
{
string #OrdNumLG = OrderNumberSM;
List<TABLE_NAME> OrdNo = new List<TABLE_NAME>();
using (CONNECTION_NAME pubs = new CONNECTION_NAME())
{
var OrdNo_LINES = (from p in pubs.TABLE_NAME select p.OrderNumber == #OrdNumLG);
foreach (TABLE_NAME OrderLine in OrdNo_LINES)
{
TABLE_NAME a = new TABLE_NAME();
a.ItemNumber = OrderLine.ItemNumber;
a.LineNumber = OrderLine.LineNumber;
a.OrderNumber = OrderLine.OrderNumber;
OrdNo.Add(a);
}
}
return OrdNo;
}
code
The foreach is giving error "Cannot convert type 'bool' to 'CONNECTION_NAME.TABLE_NAME'"
Any help with this, or a better way to return the full result set, would be appreciated.
As the error says, it's a type conversion problem.
You need to
var OrdNo_LINES = (from p in pubs.TABLE_NAME select p.OrderNumber = #OrdNumLG);
replace
var OrdNo_LINES = (from p in pubs.TABLE_NAME select p.OrderNumber == #OrdNumLG);
Found what will work...
[WebMethod]
public List<TABLE_NAME> GetAllLineInfoDetailes(string OrderNumberSM)
{
string #OrdNumSM = OrderNumberSM;
using (CONNECTION_NAME pubs = new CONNECTION_NAME())
{
var query = (from c in pubs.TABLE_NAME
where c.OrderNumber == #OrdNumSM
orderby c.LineNumber ascending
select c).ToList();
return query;
}
}
I have a checklist, column C indicates which test is automated by "enabled" or "disabled" written in the cells.
Further down the row is a column for the the Pass / Empty column for each test.
I have code that looks for if Enabled in column C, in X column on that row, mark as Pass automatically (or 'P' in my case).
The problem: If C column contains "Disabled" but also a Pass, when I run the script it replaces that Pass with an empty cell. How can I change the else statement to just ignore that cell and leave whatever is in it for anything but Enabled condition is met
function autoPassPC() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Aug 2020');
// What to put in the test result
var values1 = "P";
// Where to look for Auto:
var values2 = sheet.getRange("C10:C15" + sheet.getLastRow()).getValues();
// Keyword to look for in Auto: column
var putValues = [];
for (var i = 0; i < values2.length; i++) {
if (values2[i][0] === "Enabled") {
putValues.push([values1]);
} else {
putValues.push([""]);
}
}
// Put value1 inside row, column# for test result
sheet.getRange(10, 25, putValues.length, 1).setValues(putValues);
}
Basically how do I get rid of
} else {
putValues.push([""]);
}
properly? Just deleting this causes the script to put 'P' on every single row. Just want it to ignore the cells instead.
Thanks!
Removing the else statement will actually skip the row, but as soon as you skip a row, all following values in putValues will be on the wrong row. Instead of "skipping", try pushing the already existing value into putValues.
function autoPassPC() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Aug 2020');
// What to put in the test result
var values1 = "P";
// Where to look for Auto:
var enabledDisabled = sheet.getRange("C10:C15" + sheet.getLastRow()).getValues();
var testResultsRange = sheet.getRange("X10:X15" + sheet.getLastRow());
var testResults = testResultsRange.getValues();
// Keyword to look for in Auto: column
var putValues = [];
for (var i = 0; i < enabledDisabled.length; i++) {
if (enabledDisabled[i][0] === "Enabled") {
putValues.push([values1]);
} else {
putValues.push([testResults[i][0]]); // Push the existing cell value
}
}
// Put value1 inside row, column# for test result
testResultsRange.setValues(putValues);
}
You could also try getting the entire table at once thus having only one getValues() call.
Hello I would like create special page for private use for where i will be have possibility to change data source value for each rendering item.
I have created next code, but it dos't save any changes to items.
SC.Data.Database master = SC.Configuration.Factory.GetDatabase("master");
SC.Data.Items.Item itm = master.GetItem(tbPath.Text);
if (itm != null)
{
// Get the sublayout to update
//string sublayout_name = txtSublayout.Text.Trim();
//if (!string.IsNullOrEmpty(sublayout_name))
{
// Get the renderings on the item
RenderingReference[] refs = itm.Visualization.GetRenderings(SC.Context.Device, true);
if (refs.Any())
{
//var data = refs.Select(d=>d);
//refs[0].Settings.DataSource
var sb = new StringBuilder();
using (new SC.SecurityModel.SecurityDisabler())
{
itm.Editing.BeginEdit();
foreach (var d in refs)
{
if (d.Settings.DataSource.Contains("/sitecore/content/Site Configuration/"))
{
var newds = d.Settings.DataSource.Replace("/sitecore/content/Site Configuration/", "/sitecore/content/Site Configuration/" + tbLanguage.Text + "/");
// sb.AppendLine(string.Format("{0} old: {1} new: {2}<br/>", d.Placeholder, d.Settings.DataSource, newds));
d.Settings.DataSource = newds;
}
}
itm.Editing.EndEdit();
}
//lblResult.Text = sb.ToString();
}
}
}
how I can change data source ?
thanks
You're mixing up two different things in Sitecore here.
The datasource that is assigned to a rendering at run-time, when Sitecore is rendering a page
The datasource that is assigned to the presentation details of an item
The simplest approach to achieve what I think you're trying to achieve, would be this.
Item itm = database.GetItem("your item");
string presentationXml = itm["__renderings"];
itm.Editing.BeginEdit();
presentationXml.Replace("what you're looking for", "what you want to replace it with");
itm.Editing.EndEdit();
(I've not compiled and run this code, but it should pretty much work as is)
You are not saving the changes to the field.
Use the LayoutDefinitation class to parse the layout field, and foreach all the device definition, and rendering definitions.
And finaly commit the LayoutDifinition to the layout field.
SC.Data.Items.Item itm = master.GetItem(tbPath.Text);
var layoutField = itm.Fields[Sitecore.FieldIDs.LayoutField];
LayoutDefinition layout = LayoutDefinition.Parse(layoutField.Value);
for (int i = 0; i < layout.Devices.Count; i++)
{
DeviceDefinition device = layout.Devices[i] as DeviceDefinition;
for (int j = 0; j < device.Renderings.Count; j++)
{
RenderingDefinition rendering = device.Renderings[j] as RenderingDefinition;
rendering.Datasource = rendering.DataSource.Replace("/sitecore/content/Site Configuration/",
"/sitecore/content/Site Configuration/" + tbLanguage.Text + "/");
}
}
itm.Editing.BeginEdit();
var xml =layout.ToXml()
layoutField.Value = xml;
itm.Editing.EndEdit();
The code is not testet, but are changed from something i have in production to replace datasources on a copy event
If any one looking for single line Linq : (Tested)
var layoutField = item.Fields[Sitecore.FieldIDs.LayoutField];
if (layoutField != null)
{
var layout = LayoutDefinition.Parse(layoutField.Value);
if (layout != null)
{
foreach (var rendering in layout.Devices.Cast<DeviceDefinition>()
.SelectMany
(device => device.Renderings.Cast<RenderingDefinition>()
.Where
(rendering => rendering.ItemID == "RenderingYoulooking")))
{
rendering.Datasource = "IDYouWantToInsert";
}
layoutField.Value = layout.ToXml();
}
}
I need to generate some data to unit test my repositories. i was using a loop to generate a list of objects, see codes below. I learned moq is a great mocking library, Can I use moq to generate that and how do I do it?
public IQueryable<Category> GetCategories()
{
IList<Category> result = new List<Category>();
for (int i = 1; i <= 2; i++)
{
Category c = new Category();
c.ID = i;
c.Name = "Parent" + i.ToString();
c.ParentID = 0;
for (int x = i*10; x < i*10+5; x++)
{
Category sub = new Category();
sub.ID = x;
sub.Name = "Sub" + x.ToString();
sub.ParentID = i;
result.Add(sub);
}
result.Add(c);
}
return result.AsQueryable<Category>();
}
You can't use Moq to create the data, but you can use AutoFixture:
public IQueryable<Category> GetCategories()
{
return fixture.CreateMany<Category>().AsQueryable();
}
However, this will not give you a hierarchical tree. It will return objects like this:
Object 1:
- ID = 0
- ParentID = 1
Object 2:
- ID = 2
- ParentID = 3
etc.
If you really need to have this hierarchical data, you would need to use the following code:
public IQueryable<Category> GetCategories()
{
var result = new List<Category>();
// Create the parents
var parents = fixture.Build<Category>()
.Without(x => x.ParentID)
.CreateMany());
result.AddRange(parents);
result.AddRange(parents.SelectMany(p => fixture.Build<Category>()
.With(x => x.ParentID, p.ID)
.CreateMany()));
return result.AsQueryable();
}
This will add multiple parents with multiple subs for each parent.
You can use faker.net to generate fake data. for Example: for dotnet core project its Faker.NETCore.
dotnet add package Faker.NETCore -v 1.0.1
and then use the same in your code in the following manner:-
public void GetStudent()
{
var st = new Student()
st.FirstName = Faker.Name.First();
st.LastName = Faker.Name.Last();
st.Mobile = Faker.Phone.Number();
}
I am able to retrieve database values and insert database values, but I can't figure out what the Update() syntax should be with a where statement.
Environment -> ASP.Net, C#
Settings.ttinclude
const string Namespace = "subsonic_db.Data";
const string ConnectionStringName = "subsonic_dbConnectionString";
//This is the name of your database and is used in naming
//the repository. By default we set it to the connection string name
const string DatabaseName = "subsonic_db";
Retreive example
var product = equipment.SingleOrDefault(x => x.id == 1);
Insert Example
equipment my_equipment = new equipment();
try
{
// insert
my_equipment.parent_id = 0;
my_equipment.primary_id = 0;
my_equipment.product_code = product_code.Text;
my_equipment.product_description = product_description.Text;
my_equipment.product_type_id = Convert.ToInt32(product_type_id.SelectedItem.Value);
my_equipment.created_date = DateTime.Now;
my_equipment.serial_number = serial_number.Text;
my_equipment.Save();
}
catch (Exception err)
{
lblError.Text = err.Message;
}
Edit: Think that I was just too tired last night, it is pretty easy to update. Just use the retrieve function and use the Update() on that.
var equip = Equipment.SingleOrDefault(x => x.id == 1);
lblGeneral.Text = equip.product_description;
equip.product_description = "Test";
equip.Update();
Resolved. View answer above.