|
I am considering a change to the way I return objects from my DAL. I would like your opinion on this design.
Currently each method in the DAL returns void, an Entity, or a List<[SomeEntity]>. So as an example, my AddLookup method looks like this:
public LookupEntity AddLookup(LookupEntity entity)
{
using (FMGDataContext dc = getDataContext())
{
var lookupExists = dc.Lookups.Where(l => l.Caption.Trim().ToLower() == entity.Caption.Trim().ToLower() &&
l.LookupCode.Trim().ToLower() == entity.LookupCode.Trim().ToLower()).Any();
if (!lookupExists)
{
Lookup newLookup = new Lookup
{
LookupCode = entity.LookupCode,
LookupTypeName = entity.LookupTypeName,
Caption = entity.Caption,
Description = entity.Description,
ParentId = entity.ParentId ?? 0,
};
dc.Lookups.InsertOnSubmit(newLookup);
try
{
dc.SubmitChanges();
entity.Id = newLookup.LookupId;
}
catch (Exception e)
{
}
}
else
{
throw new DuplicateLookupException(string.Format("Lookup {0} already exists", entity.Caption));
}
}
return entity;
}
Instead, I'm considering changing all my methods to return an instance of a response object:
public class _ResponseBase
{
[DataMember]
public Result Result { get; set; }
[DataMember]
public string Message { get; set; }
private Exception _Exception;
[DataMember]
public Exception Exception
{
get { return _Exception; }
set
{
if (_Exception != value)
{
_Exception = value;
Message = _Exception.Message;
Result = Result.Failure;
}
}
}
}
So now the AddLookup method would be:
public AddLookupResponse AddLookup(LookupEntity entity)
{
AddLookupResponse response = new AddLookupResponse();
using (FalconDataContext dc = getDataContext())
{
bool exsits = (from l in dc.Lookups
where l.LookupCode.Trim().ToLower() == entity.LookupCode.Trim().ToLower()
select l).Any();
if (exsits)
{
response.Result = Result.Failure;
response.Message = string.Format("Lookup code '{0}' already exists in the Lookups table", entity.LookupCode);
}
else
{
Lookup newRecord = new Lookup
{
LookupCode = entity.LookupCode,
LookupName = entity.LookupName,
Caption = entity.Caption,
Description = entity.Description,
SystemCode = entity.SystemCode,
ParentId = entity.ParentId
};
dc.Lookups.InsertOnSubmit(newRecord);
try
{
dc.SubmitChanges();
entity.Id = newRecord.LookupId;
response.Data = entity;
}
catch (Exception e)
{
response.Exception = e;
}
}
}
return response;
}
There are some good advantages of this design:
1. The ability to return more robust data & information back to the UI.
2. A consistent design pattern across all layers
3. Better exception handling
There also some drawbacks:
1. All calls to the DAL from the UI would now have to look like this:
AddLookupResponse response = Engine.APIProxy.AddLookup(SelectedLookupItem);
if (response.Result == Result.Success)
{
}
else
{
HandleResponse(response);
}
2. There is more code for each method, even though it allows all the handling to be done in the UI.
I welcome your comments.
Thanks
If it's not broken, fix it until it is
|
|
|
|
|
IMHO, there are several issues with this design.
AddLookup() should execute within a transaction, since a LookupEntity could be inserted between the check and your insert.
- The case-insensitive string compare is flawed on several fronts: (1) A
.ToLower() compare will not work across all cultures. Instead use .ToUpperInvariant() . (2) Performing a case conversion is a performance bottleneck, since your code won't scale. Try running the compare on a million records containing large strings. Instead, perform a case-insensitive using string.Equals() with StringComparison.OrdinalIgnoreCase .
- The value of
_ResponseBase.Message depends on the order in which the instance's properties are set. This is a VBT. _ResponseBase should instead offer various constructors that set its different properties, all of which should have protected setters and public getters.
- Exceptions should be thrown, not returned. The only exception (pun intended) to this rule is when the thrown exception cannot be relayed across the network (e.g. ASP .NET MVC server exception to JS client layer).
/ravi
|
|
|
|
|
1. AddLookup() should execute within a transaction, since a LookupEntity could be inserted between the check and your insert.
I agree
2. The case-insensitive string compare is flawed on several fronts: (1) A .ToLower() compare will not work across all cultures. Instead use .ToUpperInvariant(). (2) Performing a case conversion is a performance bottleneck, since your code won't scale. Try running the compare on a million records containing large strings. Instead, perform a case-insensitive using string.Equals() with StringComparison.OrdinalIgnoreCase.
I agree
3. The value of _ResponseBase.Message depends on the order in which the instance's properties are set. This is a VBT. _ResponseBase should instead offer various constructors that set its different properties, all of which should have protected setters and public getters.
First, what's a VBT?
Second, I've never been a fan of having various constructors just to set properties. In my app, I always create a response first, then later in the method I set the properties I need. Then return the instance. Using CTOR's means having different "new MyReponse(property = value)" all over each method.
4. Exceptions should be thrown, not returned. The only exception (pun intended) to this rule is when the thrown exception cannot be relayed across the network (e.g. ASP .NET MVC server exception to JS client layer
This point is the real reason for my posting...
One problem I was having is when an exception occurred in the DAL/BL, the controller only returns "An exception has occurred". So I decided to create the responses to that I would always get something back.
Also, I've heard people say "Exceptions should be thrown, not returned", but I have yet to see a compelling reason why. The UI needs to know about the exception somehow. I just return it, then re-throw it in my HandleResponse to my exception handling routine can handle it. I means less code, a single place to handle exceptions, and a known format coming back in all cases.
Having said all this, I'm not really sold on this design, so feel free to rebut.
If it's not broken, fix it until it is
|
|
|
|
|
Kevin Marois wrote: what's a VBT? VBT == Very Bad Thing™
Kevin Marois wrote: I've never been a fan of having various constructors just to set properties. There are 2 benefits to initialization during construction: (1) Constructors allow dependency injection and therefore TDD. (2) Constructors guarantee a new instance can never exist in a malformed manner.
Your properties are badly designed (if you'll permit me this comment). The following pieces of code cause different results, which is a VBT.
_ResponseBase rb1 = new _ResponseBase();
rb1.Exception = new Exception ("foo");
rb1.Message = "bar";
_ResponseBase rb2 = new _ResponseBase();
rb2.Message = "bar";
rb2.Exception = new Exception ("foo");
/ravi
|
|
|
|
|
Ok, you're right. I see your point.
Aside from this, any other thoughts about my overall design? See any issues using responses?
If it's not broken, fix it until it is
|
|
|
|
|
I need to develop an application x32 on Windows 7 64-bit (MS Visual Studio 2010 and .net 2.0 - .net 3.5) that uses an x32 usb driver to connect an industrial equipement with 3 NI 32x dll references to run on a 32-bit Windows 7 ebedded pc.
I have tryed to develop a simple test application on my WinXP 32-bit laptop (it old, slow and has a small screen), and it works very fine on the Windows 7 embedded pc.
If I run my application with Platform 64-bit and targetting x64 and using x64 dll references it is also all ok with all the external equipements connected, but obviously I cannot run this application on the Windows 7 embedded 32x.
My question is: Is it possible to develop the whole aplication on Windows 7 64-bit that uses the 32x NI dll references and output an aplication to test on this machine and to upload and run on Windows 7 embedded 32-bit? Maybe using DPInst ...
Thanks to all!
|
|
|
|
|
Yes.
Open your project in VS, and double click the "Properties" branch in the Solution Explorer pane.
Select the "Build" tab on the left hand side, and change "Platform target" to "x86"
Rebuild your project - you may have to remove and re-add your references.
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
I have tried many times, changing Platform target to "x32" doesn't work and Microsoft says: "You need to install 64-bit drivers for all your hardware devices to get the correct functioning in a 64-bit version of Windows. Drivers designed for Windows versions 32-bit will not work on computers running 64-bit versions of Windows. ".
|
|
|
|
|
how to code to c# method call on html anchor tag but that anchor tag is placed in datalist.
|
|
|
|
|
You would probably have better luck getting an answer if you posted in the web development forum.
|
|
|
|
|
I am currently getting an error that I am having a bit of trouble trying to figure out here is the code below that I am working with:
Xaml Code:
<DataGrid Height="418" VerticalAlignment="Top" IsReadOnly="True" Width="846" ItemsSource="{Binding Path=MyDataBinding}" Name="datagrid1" BorderBrush="#FF0C5900" Style="{DynamicResource DataGridStyle1}" Background="#FF1F1F1F" ColumnHeaderHeight="30" ColumnWidth="127" BorderThickness="1,0,0,1" SelectionMode="Single" RowHeight="40" FontSize="14">
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="MouseDoubleClick" Handler="DataGrid_MouseDoubleClick"/>
</Style>
</DataGrid.RowStyle>
</DataGrid>
private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
DataGridRow dgr = sender as DataGridRow;
DataRowView drv = dgr.DataContext as DataRowView;
string hybridInfo = drv.Row["HybridInfo"].ToString();
conConnect = new SqlConnection("Data Source=GERRY;Initial Catalog=MMJDB;Integrated Security=True");
SqlCommand cmd = new SqlCommand("SELECT * FROM StrainInfo WHERE HybridInfo=@HybridInfo");
cmd.Connection = conConnect;
cmd.Parameters.AddWithValue("@HybridInfo", hybridInfo);
conConnect.Open();
dAdapter = new SqlDataAdapter(cmd);
DS = new DataSet();
dAdapter.Fill(DS, "MyDataBinding");
datagrid2.ItemsSource = DS.Tables[0].AsDataView();
dAdapter.Dispose();
conConnect.Close();
}
The line of code that is producing the following error:
A first chance exception of type 'System.ArgumentException' occurred in System.Data.dll
Additional information: Column 'HybridInfo' does not belong to table MyDataBinding
string hybridInfo = drv.Row["HybridInfo"].ToString();
modified 19-Apr-14 14:59pm.
|
|
|
|
|
Check your MMJDB database table and see if it has a column named HybridInfo.
|
|
|
|
|
Yeah I have a column named HybridInfo that shows up in Visual Studio under the MMJDBDataSet.xsd file and In Sql Server Management Studio.
The HybridInfo Column is under the StrainInfo Table.
modified 19-Apr-14 18:54pm.
|
|
|
|
|
Then you should probably debug your code to find out why your query is not returning the results you expect.
|
|
|
|
|
I have been debugging the code and eve inserted a break point. I even went as far as remaking the entire Database and resetting the Primary Keys.
|
|
|
|
|
Well I sure don't know what to tell you. The error message is very clear and specific. Either your query is bad or you are feeding your query bad information.
|
|
|
|
|
The message is telling you what is wrong; you need to check your binding to see why this column does not exist in the row.
|
|
|
|
|
Hello,
I have UTM coordinates ( North and East) that I would like to transform into pixels for plotting on a form. Can someone advise me how to do this with the transformation feature in C#.
Thanks,
Ron
|
|
|
|
|
I'm currently stuck in a exercise I'm doing and I fear I may be over thinking this, I'm trying to set up the code for a Line class and have two other Line classes each with their own thickness but can't think of anyother way besides g.DrawLine(Pens.Black, 50, 40, 126, 211); and because from how I have my code set up from class with having the DefaultLineThickness it won't cut it.
I've researched but found nothing but simple examples such as the one given and played around different methods. If anyone could help me out it'd be much appreciative. This is my current stand point.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Bicycle
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
LineOne l1 = new LineOne(new PointF(50, 40, 126, 211);
l1.setFilledState(false);
l1.setLineColor(Color.Black);
l1.Draw(g);
sRectangle r2 = new sRectangle(new PointF(151, 160));
r2.setFilledState(true);
r2.setLineColor(Color.Green);
r2.setFilledColor(Color.Honeydew);
r2.Draw(g);
sRectangleEmpty r1 = new sRectangleEmpty(new PointF(150, 150));
r1.setFilledState(false);
r1.setLineColor(Color.Blue);
r1.Draw(g);
sCircle c1 = new sCircle(new PointF(180, 130));
c1.setFilledState(true);
c1.setLineColor(Color.Orange);
c1.setFilledColor(Color.Ivory);
c1.Draw(g);
sCircleEmpty c2 = new sCircleEmpty(new PointF(120, 130));
c2.setFilledState(false);
c2.setLineColor(Color.Black);
c2.Draw(g);
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace Bicycle
{
class Shape
{
private Color DefaultLineColor = Color.Black;
private Color DefaultFillColor = Color.Blue;
private float DefaultLineThickness = 2;
protected bool bOutLine;
protected bool bFilled;
protected Pen pen;
protected Brush brush;
protected PointF location;
private void setDrawingAttributes()
{
pen = new Pen(DefaultLineColor, DefaultLineThickness);
brush = new SolidBrush(DefaultFillColor);
}
private void init()
{
bOutLine = true;
setDrawingAttributes();
}
public Shape()
{
init();
}
public Shape(PointF p)
{
location = p;
init();
}
public Color getFillColor()
{
return (DefaultFillColor);
}
public bool getFilledState()
{
return (bFilled);
}
public Color getLineColor()
{
return (DefaultLineColor);
}
public float getLineThickness()
{
return (DefaultLineThickness);
}
public bool getOutLineState()
{
return (bOutLine);
}
public bool isOutLine()
{
return (bOutLine);
}
public bool isFilled()
{
return (bFilled);
}
public void setFilledColor(Color C)
{
DefaultFillColor = C;
setDrawingAttributes();
}
public void setLineColor(Color C)
{
DefaultLineColor = C;
setDrawingAttributes();
}
public void setLineThickness(float value)
{
DefaultLineThickness = value;
setDrawingAttributes();
}
public void setFilledState(bool value)
{
bFilled = value;
}
public void setOutLineState(bool value)
{
bOutLine = value;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace Bicycle
{
class sRectangle
: Shape
{
private bool bCenterPivot = true;
private float width = 20;
private float height = 20;
protected RectangleF rect;
private SizeF size;
private void initRectangle()
{
SizeF offset = new SizeF(size.Width / 2, size.Height / 2);
PointF p1 = PointF.Subtract(location, offset);
rect = new RectangleF(p1, size);
}
private void init()
{
bCenterPivot = true;
initRectangle();
setLineColor(Color.DarkBlue);
}
public sRectangle()
{
size = new SizeF(width, height);
init();
}
public sRectangle(PointF p)
: base(p)
{
size = new SizeF(width, height);
init();
}
public SizeF getSize()
{
return (size);
}
public void setSize(float value)
{
size = new SizeF(value, value);
initRectangle();
}
public void setSize(float W, float H)
{
width = W;
height = H;
size = new SizeF(width, height);
initRectangle();
}
public virtual void Draw(Graphics g)
{
if (bFilled)
g.FillRectangle(brush, rect);
if (bOutLine)
g.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace Bicycle
{
class sRectangleEmpty
: Shape
{
private bool bCenterPivot = true;
private float width = 100;
private float height = 100;
protected RectangleF rect;
private SizeF size;
private void initRectangle()
{
SizeF offset = new SizeF(size.Width / 2, size.Height / 2);
PointF p1 = PointF.Subtract(location, offset);
rect = new RectangleF(p1, size);
}
private void init()
{
bCenterPivot = true;
initRectangle();
setLineColor(Color.Purple);
}
public sRectangleEmpty()
{
size = new SizeF(width, height);
init();
}
public sRectangleEmpty(PointF p)
: base(p)
{
size = new SizeF(width, height);
init();
}
public SizeF getSize()
{
return (size);
}
public void setSize(float value)
{
size = new SizeF(value, value);
initRectangle();
}
public void setSize(float W, float H)
{
width = W;
height = H;
size = new SizeF(width, height);
initRectangle();
}
public virtual void Draw(Graphics g)
{
if (bOutLine)
g.DrawRectangle(pen, rect.X, rect.Y, rect.Width, rect.Height);
}
}
}
|
|
|
|
|
I don't see a definition for LineOne anywhere in the above. Why not edit your question, remove most of the code and just show us the LineOne class and the implementations you want?
|
|
|
|
|
Is there an add on or functionality to insert a partial snippet. I an forever getting half way through a delegate and wanting to insert the tail from a snippet.
dsDashboard.DashboardSelect(VML.PeriodVMStatic.CurrentPeriod.PeriodID, (sErrorMsg, lResult) =>
{
ShowError(sErrorMsg);
xxxList = lResult;
});
I would like to get to the comma in the above statement and there insert the bold tail.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
If you are using Visual Studio or Visual C# Express, you can create and save code snippets, and later, insert them into your code.
|
|
|
|
|
Code snippets can only be invoked from an empty line (I have about 20 standard ones set up) I am after the ability to invoke it in a partial line.
Never underestimate the power of human stupidity
RAH
|
|
|
|
|
Mycroft Holmes wrote: Code snippets can only be invoked from an empty line
Um.
Not for me...I have a standard snippet to insert a new event: A Simple Code Snippet to Add an Event[^] which works from "evh" [TAB][TAB]. And if I do this:
string hello = evh
And press Tab twice, I get this:
string hello = /// <summary>
/// Event to indicate Description
/// </summary>
public event EventHandler Name;
/// <summary>
/// Called to signal to subscribers that Description
/// </summary>
/// <param name="e"></param>
protected virtual void OnName(EventArgs e)
{
EventHandler eh = Name;
if (eh != null)
{
eh(this, e);
}
} and the cursor is ready to enter the Description.
So can't you do something like this?
Those who fail to learn history are doomed to repeat it. --- George Santayana (December 16, 1863 – September 26, 1952)
Those who fail to clear history are doomed to explain it. --- OriginalGriff (February 24, 1959 – ∞)
|
|
|
|
|
You will see a conceptual framework that I came up with, to the best of my understanding, as I have never worked with the project.
NONMEM (http://www.iconplc.c...roducts/nonmem/) is a software that analysis data that helps provide predictions on a population level, instead of on a single patient. A statistician is responsible to analyse these given data and provide models (sorry, not modules), which are sophisticated mathematical equations, that help predict level of drug concentrations in the blood. Ultimately, we take this data and predict the appropriate doses (output).
So, the statistician will provide the csv file with the required data to be applied to the model. On what bases the model to be chosen, this yet to be figured out. However, I can speculate that the model to be applied to according to its respective product/drug. For example, patient need drug A, so model C corresponds to that drug. Therefore, I want the csv file to be applied to model C because that patient will use drug A.
Does that make sense?
|
|
|
|
|