Permission to enable certain fields depends on CurrentUserID Epicor ERP10 - epicorerp

I need help. I need to enable certain fields depends on CurrentUserID. There is one field which is UltraCombo contains of Employee's name. When the Employee's Name is selected, the other fields should be enabled if the CurrentUserID is matched with the selected Employee's name. Otherwise, the other fields should be locked. I tried to use the CanView method in the code but I don't know how to call in SQL command. Plese help me T-T
private bool CanView(string field)
{
bool result = true;
EpiDataView edv = oTrans.EpiDataViews["CallContextClientData"] as EpiDataView;
string CurrentUser = edv.dataView[edv.Row]["CurrentUserId"].ToString();
string ConnectionString = "Data Source=RWNAERP;Initial Catalog=ERP10TESTRWNA;Persist Security Info=True;User ID=sa;Password=Epicor10";
string CompanyId = ((Ice.Core.Session)(oTrans.Session)).CompanyID;
string UserID = ((Ice.Core.Session)(oTrans.Session)).UserID;
using (SqlConnection connection1 = new SqlConnection(ConnectionString))
{
DataTable dt = new DataTable();
connection1.Open();
SqlCommand cmd = new SqlCommand("SELECT DcdUserID FROM dbo.UserFile WHERE Name=#Name AND EmpID=#EmpID", connection1);
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("DcdUserID", SqlDbType.NVarChar).Value = UserID;
SqlDataAdapter sqlDa = new SqlDataAdapter(cmd);
sqlDa.Fill(dt);
if (dt.Rows.Count > 0)
{
result = false;
}
if (CurrentUser != "")
{
result = true;
}
connection1.Close();
connection1.Dispose();
}

What you are trying to do is on the client, but the client only connects to the AppServer and never to the SQL Database. Only the AppServer should connect to the database.
Assuming you are adding this code as a customisation script, it's much easier to get the current user info from the Session variable i.e.
var session = (Ice.Core.Session)oTrans.Session;
var userId = session.UserID;
var userName = session.UserName;
var userEmail = session.UserEmail;
In the Epicor.exe client disabling fields is best done with a RowRule, i.e.
var callContextClientData = oTrans.Factory("CallContextClientData");
var disableFieldsForUser = new RowRule("CurrentUserId", RuleCondition.Equals, ((Ice.Core.Session)trans.Session).UserID);
disableFieldsForUser.AddAction(RuleAction.AddControlSettings(stockDtlEpiDataView, "CallContextClientData.ShortChar01", SettingStyle.Disabled));
callContextClientData.AddRowRule(disableFieldsForUser);
It's not clear which fields you are matching or which you want to disable, but hopefully this should get you started.

Related

C# Core, OracleDataReader with hasRows as false while select all rows in a table that has data

I am testing Oracle database. I wrote some code but my datareader has no rows, why? My "carros" table has data and I am selecting all of them but I am getting an empty result set it seems.
string constr = "Data Source=localhost:1521/XE;User Id=System;Password=password;";
OracleConnection con = new OracleConnection(constr);
OracleCommand oracleCommand = new OracleCommand();
oracleCommand.Connection = con;
oracleCommand.CommandText = "select preco from carro";
con.Open();
OracleDataReader oracleDataReader = oracleCommand.ExecuteReader();
string resultado = String.Empty;
//My test, I got hasRows as false
if (oracleDataReader.HasRows == false)
{
resultado = "no results";
}
//never enters this loop.
while (oracleDataReader.Read())
{
resultado += (string)oracleDataReader["preco"];
}
// Close and Dispose OracleConnection
con.Close();
con.Dispose();
return resultado;
If HasRows is false after ExecuteReader, the problem is simply that the query is returning no rows so Read will return false as well. Perhaps the someValue variable is not set correctly.
From you description, it seems that your table is named carros while your query has used carro. Try to use
oracleCommand.CommandText = "select preco from carros";
A path towards solving this can include a scattering of logging commands that write to the file system.
System.IO.File.AppendAllText(#"\\server\\C\\log.txt", "put error message here" + "\r\n");
Or for printing a variable:
System.IO.File.AppendAllText(#"\\server\\C\\log.txt", ex.ToString() + "\r\n");
Pepper variations of this command throughout your script to see where failures are happening and to validate variable values.

Using Dapper QueryMultiple in Oracle

I´m trying to use dapper with Oracle (ODP.NET) and I would like to use the "QueryMultiple" functionality.
Passing this string to the QueryMultiple method:
var query = "Select CUST_ID CustId from Customer_info WHERE CUST_ID=:custId;" +
"Select CUST_ID CustId from BCR WHERE CUST_ID=:custId";
I´m getting a ORA-00911: invalid character error
Is there any way to do this or it´s not possible?
Tks
The OP has probably long since solved the issue by now, but as of the time of writing, this question has only one answer and it doesn't really solve the problem of using Dapper's QueryMultiple() method with Oracle. As #Kamolas81 correctly states, by using the syntax from the official examples, one will indeed get the ORA-00933: SQL command not properly ended error message. I spent a while searching for some sort of documentation about how to do QueryMultiple() with Oracle, but I was surprised that there wasn't really one place that had an answer. I would have thought this to be a fairly common task. I thought that I'd post an answer here to save me :) someone some time in the future just in case anybody happens to have this same problem.
Dapper seems to just pass the SQL command straight along to ADO.NET and whatever db provider is executing the command. In the syntax from the examples, where each command is separated by a line break, SQL server will interpret that as multiple queries to run against the database and it will run each of the queries and return the results into separate outputs. I'm not an ADO.NET expert, so I might be messing up the terminology, but the end effect is that Dapper gets the multiple query outputs and then works its magic.
Oracle, though, doesn't recognize the multiple queries; it thinks that the SQL command is malformed and returns the ORA-00933 message. The solution is to use cursors and return the output in a DynamicParameters collection. For example, whereas the SQL Server version would look like this:
var sql =
#"
select * from Customers where CustomerId = #id
select * from Orders where CustomerId = #id
select * from Returns where CustomerId = #id";
the Oracle version of the query would need to look like this:
var sql = "BEGIN OPEN :rslt1 FOR SELECT * FROM customers WHERE customerid = :id; " +
"OPEN :rslt2 FOR SELECT * FROM orders WHERE customerid = :id; " +
"OPEN :rslt3 FOR SELECT * FROM returns Where customerid = :id; " +
"END;";
For queries run against SQL Server, Dapper can handle it from there. However, because we're returning the result sets into cursor parameters, we'll need to use an IDynamicParameters collection to specify parameters for the command. To add an extra wrinkle, the normal DynamicParameters.Add() method in Dapper uses a System.Data.DbType for the optional dbType parameter, but the cursor parameters for the query need to be of type Oracle.ManagedDataAccess.Client.OracleDbType.RefCursor. To solve this, I used the solution which #Daniel Smith proposed in this answer and created a custom implementation of the IDynamicParameters interface:
using Dapper;
using Oracle.ManagedDataAccess.Client;
using System.Data;
public class OracleDynamicParameters : SqlMapper.IDynamicParameters
{
private readonly DynamicParameters dynamicParameters = new DynamicParameters();
private readonly List<OracleParameter> oracleParameters = new List<OracleParameter>();
public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction, object value = null, int? size = null)
{
OracleParameter oracleParameter;
if (size.HasValue)
{
oracleParameter = new OracleParameter(name, oracleDbType, size.Value, value, direction);
}
else
{
oracleParameter = new OracleParameter(name, oracleDbType, value, direction);
}
oracleParameters.Add(oracleParameter);
}
public void Add(string name, OracleDbType oracleDbType, ParameterDirection direction)
{
var oracleParameter = new OracleParameter(name, oracleDbType, direction);
oracleParameters.Add(oracleParameter);
}
public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
((SqlMapper.IDynamicParameters)dynamicParameters).AddParameters(command, identity);
var oracleCommand = command as OracleCommand;
if (oracleCommand != null)
{
oracleCommand.Parameters.AddRange(oracleParameters.ToArray());
}
}
}
So all of the code together goes something like this:
using Dapper;
using Oracle.ManagedDataAccess.Client;
using System.Data;
int selectedId = 1;
var sql = "BEGIN OPEN :rslt1 FOR SELECT * FROM customers WHERE customerid = :id; " +
"OPEN :rslt2 FOR SELECT * FROM orders WHERE customerid = :id; " +
"OPEN :rslt3 FOR SELECT * FROM returns Where customerid = :id; " +
"END;";
OracleDynamicParameters dynParams = new OracleDynamicParameters();
dynParams.Add(":rslt1", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":rslt2", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":rslt3", OracleDbType.RefCursor, ParameterDirection.Output);
dynParams.Add(":id", OracleDbType.Int32, ParameterDirection.Input, selectedId);
using (IDbConnection dbConn = new OracleConnection("<conn string here>"))
{
dbConn.Open();
var multi = dbConn.QueryMultiple(sql, param: dynParams);
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
...
dbConn.Close();
}
Building on greyseal96's helpful answer, I created this implementation of IDynamicParameters:
public class OracleDynamicParameters : SqlMapper.IDynamicParameters
{
private readonly DynamicParameters dynamicParameters;
private readonly List<OracleParameter> oracleParameters = new List<OracleParameter>();
public OracleDynamicParameters(params string[] refCursorNames) {
dynamicParameters = new DynamicParameters();
AddRefCursorParameters(refCursorNames);
}
public OracleDynamicParameters(object template, params string[] refCursorNames) {
dynamicParameters = new DynamicParameters(template);
AddRefCursorParameters(refCursorNames);
}
private void AddRefCursorParameters(params string[] refCursorNames)
{
foreach (string refCursorName in refCursorNames)
{
var oracleParameter = new OracleParameter(refCursorName, OracleDbType.RefCursor, ParameterDirection.Output);
oracleParameters.Add(oracleParameter);
}
}
public void AddParameters(IDbCommand command, SqlMapper.Identity identity)
{
((SqlMapper.IDynamicParameters)dynamicParameters).AddParameters(command, identity);
var oracleCommand = command as OracleCommand;
if (oracleCommand != null)
{
oracleCommand.Parameters.AddRange(oracleParameters.ToArray());
}
}
}
Assuming the same query, it can be used so:
var queryParams = new { id };
string[] refCursorNames = { "rslt1", "rslt2", "rslt3" };
var dynParams = new OracleDynamicParameters(queryParams, refCursorNames);
...
var multi = dbConn.QueryMultiple(sql, param: dynParams);
I suspect this is two or three separate things:
Your first query should not have a semi-colon
There is no new-line character between the queries
The usage notes imply that the bind character is # not : (no idea if this depends on the RDBMS being used).
If you look at the Dapper Google Code page the example given for QueryMultiple() is:
var sql =
#"
select * from Customers where CustomerId = #id
select * from Orders where CustomerId = #id
select * from Returns where CustomerId = #id";
using (var multi = connection.QueryMultiple(sql, new {id=selectedId}))
{
var customer = multi.Read<Customer>().Single();
var orders = multi.Read<Order>().ToList();
var returns = multi.Read<Return>().ToList();
...
}
Remove the semi-colon; add a new line and if you still have issues change the bind character.

How to want to move my DAL to separate project in my MVC3 solution?

I have MVC 3 application that uses a DAL (ADO.NET) that communicates to a set of tsql stored procedures? I want to add a new MVC project to my current solution. I need to have DAL in a separate project that the 2 MVC project ("Monitor" and "Audit") can share.
Here's the current DAL (which sits in a folder of the "Monitor" MVC project) code below. My issue is I have signature like IEnumerable located in the Monitor.Models and IEnumerable located in the Audit.Models. Do I need to make the DAL generic to avoid needing to make references to the models in the DAL?
Ex:
**//Is this bad practice?**
using Monitor.Models;
using Adit.Models;
namespace Monitor.DAL
{
public class QuestionDAL
{
static ILog log = log4net.LogManager.GetLogger(typeof(QuestionDAL));
private string _connectionString = WebConfigurationManager.ConnectionStrings["NexGenContext"].ToString();
public IEnumerable<AgencyTerm> SearchAgencies(string ori, string name)
{
log.Debug("Executing: SearchAgencies(string ori, string name)");
List<AgencyTerm> agencies = new List<AgencyTerm>();
using (var conn = new SqlConnection(_connectionString))
{
var com = new SqlCommand();
com.Connection = conn;
com.CommandType = CommandType.StoredProcedure;
string term = "Ori";
if (!String.IsNullOrEmpty(ori))
{
term = "Ori";
com.Parameters.Add(new SqlParameter
{
ParameterName = "#ORI",
Value = ori
});
}
if (!String.IsNullOrEmpty(name))
{
term = "legal_name";
com.Parameters.Add(new SqlParameter
{
ParameterName = "#Name",
Value = name
});
}
com.CommandText = "Review_Get_Agency_List";
var adapt = new SqlDataAdapter();
adapt.SelectCommand = com;
var dataset = new DataSet();
adapt.Fill(dataset);
agencies = (from c in dataset.Tables[0].AsEnumerable()
select new AgencyTerm()
{
label = c[term].ToString(),
id = c["Agency_Id"].ToString()
}).ToList<AgencyTerm>();
return agencies;
}
}
public IEnumerable<User> GetUsers()
{
log.Debug("Executing: GetUsers()");
List<User> users = new List<User>();
using (var conn = new SqlConnection(_connectionString))
{
var com = new SqlCommand();
com.Connection = conn;
com.CommandType = CommandType.StoredProcedure;
com.CommandText = "Review_Get_Users";
var adapt = new SqlDataAdapter();
adapt.SelectCommand = com;
var dataset = new DataSet();
adapt.Fill(dataset);
users = (from c in dataset.Tables[0].AsEnumerable()
select new User()
{
User_ID = Convert.ToInt32(c["User_ID"]),
Department = c["Department"].ToString(),
Enabled = Convert.ToBoolean(c["Enabled"]),
Email = c["Email"].ToString(),
User_First_Name = c["User_First_Name"].ToString(),
User_Last_Name = c["User_Last_Name"].ToString(),
Location = c["Location"].ToString(),
User_Name = c["User_Name"].ToString()
}).ToList<User>();
return users;
}
}
You have two possibilities:
Either move your model into a separate library as well and then reference it from your MVC project and your DAL
Make your DAL completely generic and just push the values inside. I don't see an easy way here though since you have a lot of information in your DAL
I would go with the first option. Just extract your models to a different project and then reuse that library in both DAL and MVC-projects

Windows Azure Storage - Table not found

I'm trying to implement windows azure table storage...but I'm getting 'Table Not Found'
Here is my connection string(How post I xml here?)(sorry for links)
ServiceConfiguration.Cloud.cscfg:
http://pastebin.com/F9tuckfT
ServiceConfiguration.Local.cscfg:
http://pastebin.com/XZHEvv6g
and here there's a print screen from my windows azure portal
http://s20.postimage.org/nz1sxq7hp/print.png
The code(sorry for the longer code...but there's three pages...Login works, when I log in, go to main.aspx that call grid.aspx ...In grid.aspx I get the error "Table not found" All this code is important for the question.....) http://pastebin.com/RnuvvqsM
I have tried
private void popula()
{
var account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Conn"));
account.CreateCloudTableClient().CreateTableIfNotExist("fiscal");
var context = new CRUDManifestacoesEntities(account.TableEndpoint.ToString(), account.Credentials);
Hashtable ht = (Hashtable)ViewState["filtro"];
if (ht == null)
GridView1.DataSource = context.SelectConc(ViewState["x"].ToString());
else
GridView1.DataSource = context.SelectConc(ht);
GridView1.DataBind();
}
but it doesn't work too
Other error similar is when I try to add a USER in table
public string addusr(string nome, string cidade, string cpf, string email, string telefone)
{
try
{
if (nome.Length == 0)
return "f:Preencha o campo nome.";
if (cidade.Length == 0)
return "f:Preencha o campo cidade.";
if (cpf.Length == 0)
return "f:Preencha o campo cpf.";
if (!Valida(cpf))
return "f:CPF Invalido.";
if (email.Length == 0)
return "f:Preencha o campo email.";
Regex rg = new Regex(#"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)#([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$");
if (!rg.IsMatch(email))
{
return "f:Email Invalido";
}
List<UserEntity> lst = new List<UserEntity>();
var _account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Conn"));
_account.CreateCloudTableClient().CreateTableIfNotExist("fiscal");
var _context = new CRUDUserEntities(_account.TableEndpoint.ToString(), _account.Credentials);
var account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Conn"));
account.CreateCloudTableClient().CreateTableIfNotExist("fiscal");
var context = new CRUDUserEntities(account.TableEndpoint.ToString(), account.Credentials);
UserClientEntity entity = new UserClientEntity() { nome = nome, cidade = cidade, cpf = cpf, email = email, telefone = telefone };
context.ADDUSociate(entity);
context.SaveChanges();
return "k";
}
I'm getting this error:
f:An error occurred while processing this request.| at System.Data.Services.Client.DataServiceContext.SaveResult.HandleBatchResponse()
at System.Data.Services.Client.DataServiceContext.SaveResult.EndRequest()
at System.Data.Services.Client.DataServiceContext.SaveChanges(SaveChangesOptions options)
at AzureTableLayer.CRUDUserEntities.ADDUSociate(UserClientEntity entity)
at mobile.Service1.addusr(String nome, String cidade, String cpf, String email, String telefone)
I believe that the two problems are related
EDIT: I have debugged and discovered that the StorageClient framework could not be loaded...
I'm getting this error Could not load file or assembly Microsoft.WindowsAzure.StorageClient, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
How to solve?
How are you trying to work with Table Storage? Trought the .NET SDK? PHP? Java? Node? ... Typically if you get this error it means that... the table does not exist.
Check the SDK you're using for a method similar to CreateIfNotExists in order to create the table before you start using it.
Edit:
The issue probably happens here:
var account = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("Conn"));
var context = new CRUDManifestacoesEntities(account.TableEndpoint.ToString(), account.Credentials);
Hashtable ht = (Hashtable)ViewState["filtro"];
if (ht == null)
GridView1.DataSource = context.SelectConc(ViewState["x"].ToString());
else
GridView1.DataSource = context.SelectConc(ht);
Add the following code after the var account = ... line:
account.CreateCloudTableClient().CreateTableIfNotExist("<name of your table>");
The API has been changed. you need to do it like this:
var key = CloudConfigurationManager.GetSetting("Setting1");
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(key);
var client = storageAccount.CreateCloudTableClient();
CloudTable table = client.GetTableReference(ContactTableName);
table.CreateIfNotExists();

Update using LINQ to SQL

How can I update a record against specific id in LINQ to SQL?
LINQ is a query tool (Q = Query) - so there is no magic LINQ way to update just the single row, except through the (object-oriented) data-context (in the case of LINQ-to-SQL). To update data, you need to fetch it out, update the record, and submit the changes:
using(var ctx = new FooContext()) {
var obj = ctx.Bars.Single(x=>x.Id == id);
obj.SomeProp = 123;
ctx.SubmitChanges();
}
Or write an SP that does the same in TSQL, and expose the SP through the data-context:
using(var ctx = new FooContext()) {
ctx.UpdateBar(id, 123);
}
In the absence of more detailed info:
using(var dbContext = new dbDataContext())
{
var data = dbContext.SomeTable.SingleOrDefault(row => row.id == requiredId);
if(data != null)
{
data.SomeField = newValue;
}
dbContext.SubmitChanges();
}
AdventureWorksDataContext db = new AdventureWorksDataContext();
db.Log = Console.Out;
// Get hte first customer record
Customer c = from cust in db.Customers select cust where id = 5;
Console.WriteLine(c.CustomerType);
c.CustomerType = 'I';
db.SubmitChanges(); // Save the changes away
DataClassesDataContext dc = new DataClassesDataContext();
FamilyDetail fd = dc.FamilyDetails.Single(p => p.UserId == 1);
fd.FatherName=txtFatherName.Text;
fd.FatherMobile=txtMobile.Text;
fd.FatherOccupation=txtFatherOccu.Text;
fd.MotherName=txtMotherName.Text;
fd.MotherOccupation=txtMotherOccu.Text;
fd.Phone=txtPhoneNo.Text;
fd.Address=txtAddress.Text;
fd.GuardianName=txtGardianName.Text;
dc.SubmitChanges();
I found a workaround a week ago. You can use direct commands with "ExecuteCommand":
MDataContext dc = new MDataContext();
var flag = (from f in dc.Flags
where f.Code == Code
select f).First();
_refresh = Convert.ToBoolean(flagRefresh.Value);
if (_refresh)
{
dc.ExecuteCommand("update Flags set value = 0 where code = {0}", Code);
}
In the ExecuteCommand statement, you can send the query directly, with the value for the specific record you want to update.
value = 0 --> 0 is the new value for the record;
code = {0} --> is the field where you will send the filter value;
Code --> is the new value for the field;
I hope this reference helps.

Resources