I have added a new control to my .NET form and I want to save its value in a table.I have added a new column in my table.How do you use MyGeneration Doodads to create a data access object for this table?I have looked at http://www.mygenerationsoftware.com/portal/doodads/cusage/tabid/53/default.aspx
but I can't understand what it means by "template".What is the procedure to regenerate doodads for a table?
You wont get much of a response on this... dOOdads have not been supported for many years. Regardless, we use dOOdads too and I just roll my own repositories for my WPF projects (I know it's not ASP, but I don't think you can just "plug-and-play"). Here is an example of my base lookup class:
public abstract class BaseLookup<TEntity>
{
// Constructor
protected BaseLookup()
{
this.SubsetIdentifier = null;
}
// Properties
public virtual object SubsetIdentifier { get; set; }
// Public Methods
public abstract IEnumerable<TEntity> Read();
public virtual TEntity ReadSingle()
{
return default(TEntity);
}
// Protected Methods
/// <summary>
/// Retrieve translated entities from the database. The methods used to do this
/// are specified from the child class as parameters (i.e. Action or Func delegates).
/// </summary>
/// <param name="loadSubsetFunc">Specify how to load a set of database records.
/// Return boolean confirmation that records were found.</param>
/// <param name="orderByAction">Specify what should happen to sort the results.</param>
/// <param name="translateRowFunc">Specify how a database record should translate to
/// a model entity. Return the new entity.</param>
/// <param name="moveNextFunc">Specify how the database row pointer should move on.
/// Return FALSE on a call to the final row.</param>
/// <returns>A set of translated entities from the database.</returns>
/// <example><code>
///
/// return base.ReloadRecords(
/// _dOOdad.LoadAll,
/// () =>
/// {
/// _dOOdad.Sort = _dOOdad.GetAutoKeyColumn();
/// },
/// () =>
/// {
/// var entity = new LookupEntity();
/// return entity.PopulateLookupEntity(_dOOdad.CurrentRow.ItemArray);
/// },
/// _dOOdad.MoveNext);
///
/// </code></example>
protected virtual IEnumerable<TEntity> ReloadRecords(Func<bool> loadSubsetFunc,
Action orderByAction, Func<TEntity> translateRowFunc, Func<bool> moveNextFunc)
{
// If records are found, sort them and return set of entities
if (loadSubsetFunc())
{
orderByAction();
do
{
var entity = translateRowFunc();
yield return entity;
}
while (moveNextFunc());
}
else
{
Debug.WriteLine(
string.Format(
"# ZERO records found: Returning empty set of {0}.",
typeof(TEntity).Name));
}
}
}
And here is a concrete implementation of the base lookup:
public class CyclesLookup : BaseLookup<BaseLookupEntity>
{
// Fields & Constructor
private readonly CYCLES _dOOdad;
public CyclesLookup(IDbConnection connection, string library)
{
_dOOdad = OpenConnection(connection, library);
}
// Base Override Methods
public override IEnumerable<BaseLookupEntity> Read()
{
// Clear old result set and settings
_dOOdad.FlushData();
// Reload the records and return them sorted and translated
return base.ReloadRecords(
_dOOdad.LoadAll,
() =>
{
_dOOdad.Sort = _dOOdad.GetAutoKeyColumn();
},
() =>
{
var entity = new LookupEntity();
entity.Description = string.Format("Cycles for {0}", _dOOdad.YEAR);
return entity.PopulateLookupEntity(_dOOdad.CurrentRow.ItemArray, true);
},
_dOOdad.MoveNext);
}
// Private Helper Methods
private static CYCLES OpenConnection(IDbConnection connection, string library)
{
var dOOdad = new CYCLES(connection);
dOOdad.SchemaGlobal = library + ".";
return dOOdad;
}
}
That PopulateLookupEntity method is just an extension method:
public static T PopulateLookupEntity<T>(this T entity, object[] rowItems,
bool noDescription = false) where T : BaseLookupEntity
{
int id = 0;
int.TryParse(rowItems[0].ToString(), out id);
entity.RecordID = id;
var attributesFirstIndex = 1;
if (!noDescription)
{
entity.Description = rowItems[1].ToString();
attributesFirstIndex = 2;
}
entity.Attributes = new object[rowItems.Length - attributesFirstIndex];
for (int index = attributesFirstIndex; index < rowItems.Length; index++)
{
entity.Attributes[index - attributesFirstIndex] = rowItems[index];
}
return (T)entity;
}
For non-lookups, I have a more complex BaseRepository class that inherits from BaseLookup. With that one, I don't use PopulateLookupEntity, but a private helper method like this:
private IPlanningGridHeader TranslateCurrentDoodadRow()
{
return new PlanningGridHeader()
{
PlanNumber = Convert.ToInt32(_dOOdad.PLANNUMBER),
Active = _dOOdad.ACTIVE == 1M,
Capturer = _dOOdad.CAPTURER,
Region = _dOOdad.REGION,
CorporateID = Convert.ToInt32(_dOOdad.CORPORATEID),
StartDate = _dOOdad.STARTDATE.ConvertDb2Date(),
EndDate = _dOOdad.ENDDATE.ConvertDb2Date(),
AdvertStartDate = _dOOdad.ADVERTSTARTDATE.ConvertDb2Date(),
AdvertEndDate = _dOOdad.ADVERTENDDATE.ConvertDb2Date(),
BpcsDealNumber = Convert.ToInt32(_dOOdad.BPCSDEALNUMBER),
Description = _dOOdad.DESCRIPTION,
DeactivationReason = _dOOdad.DEACTIVATIONREASON,
LastSavedUsername = _dOOdad.LASTUSER,
LastSavedDateTime = _dOOdad.LASTDATE.ConvertDb2Date().AddDb2Time(_dOOdad.LASTTIME)
};
}
Hope this helps :-)
Although it's old but I recommend staying away from this library. It has a serious bug that cause connection leaking, I bet the creator didn't check ADO.NET practices when coding it. Moreover, he didn't know how to deal with DBNull, thus he invented "string properties" along the side of normal properties to deal with NULL problem, turned generated code and programming model into a big mess, created more NullReferenceException when developer access normal properties which has value as null.
I collected all those problems from a 10+ years old legacy system using MyGeneration Doodads. Felt very happy that I could get rid of it at last.
If you're on the way of finding a DAC library for enterprise app, just don't pick this library.
Related
I am using Cosmosdb with .net CORE 2.2 and the Cosmosdb SQL SDK. By default cosmosdb will assign every documents 'Id' property as a Guid. But the Id alone is not enough to directly read the document, you must also know its partition. So I created a class named CosmosGuid that contains a Id property(Guid) and a PartitionKey property(string). The ToString() is overridden to call .ToString("N") on the Guid to remove the dashes and it appends the PartitionKey to the end. The problem im having is when I use the CosmosGuid in Linq, the generated SQL will contain a json version of CosmosGuid, I really need it to just be a string. I can call .ToString() and that will produce the desired result, but im afraid another developer will use my class in a Linq expression and it fail for no known reason. When I save the CosmosGuid I created a custom newtonsoft converter to call ToString() when it saves and to call .Parse(string) when it reads. When you compare two Guids in Linq the generated SQL comes out to a string, but when I compare two CosmosGuid it creates a json string of my class. How can I make my class act like a Guid?
I have already attempted to implement all the same Interfaces as the Guid. The closes I have came was implementing 'IEnumerable' and in the GetComparer() I returned:
new string[] { this.ToString() }.GetEnumerator();
The code produced was perfect, but it kept putting my string surrounded with brackets[].
here is an example:
SELECT VALUE root FROM root WHERE (root['id'] = ['9a9dbbd5f78143c48b16f780c7ceaa4011'])
This is the CosmosGuid class, I figure id post the full class since its not very large and it may be useful to some.
public class CosmosGuid
{
// This is the unique Id of the entity
public Guid Guid { get; set; }
// This is the partition key where the entity lives
public string PartitionKey { get; set; }
// This is the unique Id of the Document that contains the entity
public Guid? ParentGuid { get; set; }
// This is the PartitionKey of the Document that contains the entity
public string ParentPartitionKey { get; set; }
/// <summary>
/// Parses a CosmosGuid string into a new CosmosGuid
/// </summary>
/// <param name="cosmosGuid"></param>
public CosmosGuid(string cosmosGuid)
{
ParentGuid = null;
ParentPartitionKey = null;
try
{
var parsed = cosmosGuid.Split('-');
// We can accuratly parse the guid from the string by always grabing the first 32 characters.
// The characters after the first 32 are the PartitionKey.
// https://stackoverflow.com/a/4458925
// Guid.NewGuid().ToString("N") => 32 characters (digits only, no dashes)
Guid = Guid.Parse(parsed[0].Substring(0, 32));
PartitionKey = parsed[0].Substring(32, parsed[0].Length - 32);
if (parsed.Length == 2)
{
ParentGuid = Guid.Parse(parsed[1].Substring(0, 32));
ParentPartitionKey = parsed[1].Substring(32, parsed[1].Length - 32);
}
}
catch (Exception ex)
{
throw new Exception("The Id of the document is not a properly formatted CosmosGuid.", ex);
}
}
/// <summary>
/// Generates a new Guid and appends the PartitionKey. This is used for Documents.
/// </summary>
/// <param name="partitionKey"></param>
/// <returns></returns>
public static CosmosGuid NewCosmosGuid(string partitionKey)
{
return new CosmosGuid($"{ShortenGuid(Guid.NewGuid())}{partitionKey}");
}
/// <summary>
/// Generates a new Guid and appends the PartitionKey as well as the Parent Guid and Parent PartitionKey. This is used for Subdocuments.
/// </summary>
/// <param name="parent"></param>
/// <param name="partitionKey"></param>
/// <returns></returns>
public static CosmosGuid NewCosmosGuid(CosmosGuid parent, string partitionKey)
{
return new CosmosGuid($"{ShortenGuid(Guid.NewGuid())}{partitionKey}-{ShortenGuid(parent.Guid)}{parent.PartitionKey}");
}
/// <summary>
/// Returns only the Parent CosmosGuid. If there is no parent the value returned will be null.
/// </summary>
public CosmosGuid Parent
{
get
{
if (ParentGuid != null && ParentPartitionKey != null)
return new CosmosGuid($"{ShortenGuid((Guid)ParentGuid)}{ParentPartitionKey}");
else
return null;
}
}
/// <summary>
/// Parses a CosmosGuid string into a new CosmosGuid.
/// </summary>
/// <param name="cosmosGuid"></param>
/// <returns></returns>
public static CosmosGuid Parse(string cosmosGuid)
{
return new CosmosGuid(cosmosGuid);
}
/// <summary>
/// Generates a CosmosGuid formatted string.
/// </summary>
/// <returns></returns>
public override string ToString()
{
if (ParentGuid == null)
return $"{ShortenGuid(Guid)}{PartitionKey}";
else
return $"{ShortenGuid(Guid)}{PartitionKey}-{ShortenGuid((Guid)ParentGuid)}{ParentPartitionKey}";
}
/// <summary>
/// Removes the dashes from a Guid
/// </summary>
/// <param name="guid"></param>
/// <returns></returns>
private static string ShortenGuid(Guid guid)
{
// Just remove dashes from the guid to shorten it some.
// More can be done here if you wish but make sure the guid uniqueness isnt compromised.
return guid.ToString("N");
}
public static bool operator ==(CosmosGuid obj1, CosmosGuid obj2)
{
return obj1?.ToString() == obj2?.ToString();
}
public static bool operator !=(CosmosGuid obj1, CosmosGuid obj2)
{
return obj1?.ToString() != obj2?.ToString();
}
}
If a developer where to use the CosmosGuid like so it would fail to work, because the SQL generated is a Json version of the class. (the Id is also a CosmosGuid):
var cosmosGuid = CosmosGuid.Parse("6bec688a0aca477c8175c09162b7a9b411");
var result = await Client.CreateDocumentQuery<MyClass>(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), options)
.Where(x => x.Id == cosmosGuid)
.AsDocumentQuery();
This is the sql generated
SELECT VALUE root FROM root WHERE (root['id'] = {'Guid':'6bec688a-0aca-477c-8175-c09162b7a9b4','PartitionKey':'11','ParentGuid':null,'ParentPartitionKey':null,'Parent':null})
Instead, the developer must call .ToString() everywhere in the code.
var cosmosGuid = CosmosGuid.Parse("6bec688a0aca477c8175c09162b7a9b411");
var result = await Client.CreateDocumentQuery<MyClass>(UriFactory.CreateDocumentCollectionUri(DatabaseId, CollectionId), options)
.Where(x => x.Id.ToString() == cosmosGuid.ToString())
.AsDocumentQuery();
This is the Sql generated
SELECT VALUE root FROM root WHERE (root['id'] = '6bec688a0aca477c8175c09162b7a9b411')
If I remove the CosmosGuid and revert back to using just a Guid as the Id property the SQL generated by the Cosmosdb SDK works fine. How can I make my class act like a .net Guid when used in Linq?
For LINQ to objects:
You can overload the == operator on your CosmosGuid class, see operator keyword.
Also, you could implement IEquatable<Guid> and use the .Equals() instead:
public class CosmosGuid : IEquatable<Guid>
{
....
public bool Equals(Guid other) {
return this.Guid == other;
}
}
.Where(x => cosmosGuid.Equals(x.Id))
I have stored immutable types in a temporary CQRS read store (query/read side, in fact implemented by a simple List with abstraction access layer, I don't want to use a full blown document database at this point). These read stores contains items like the following:
public class SomeItem
{
private readonly string name;
private readonly string description;
public SomeItem(string name, string description)
{
this.name = name;
this.description = description;
}
public string Name
{
get { return this.name; }
}
public string Description
{
get { return this.description; }
}
}
Now I want to change the Name and in a 2nd Command the Description.
These changes should keep the current state, which means for the example above:
// initial state
var someItem = new SomeItem("name", "description");
// update name -> newName
someItem = new SomeItem("newName", someItem.Description);
// update description -> newDescription
someItem = new SomeItem(someItem.Name, "newDescription");
This does look error prone to me if you have several properties... you have to manage keeping the current state. I could add something like Clone() to every type but I think/hope there is something better out there that performs well and is easy to use, I don't want to write much repetive code (lazy programmer). Any suggestions how to improve the code above? The SomeItem class needs to stay immutable (transported through several different threads).
Sadly, there's no simple way in C#. F# has the with keyword, and you could have a look at lenses, but it's all somewhat tedious in C#. The best I can give you is something like this:
class SomeItem
{
private readonly string name;
private readonly string description;
public SomeItem(string name, string description)
{
this.name = name;
this.description = description;
}
public SomeItem With
(
Option<string> name = null,
Option<string> description = null
)
{
return new SomeItem
(
name.GetValueOrDefault(this.name),
description.GetValueOrDefault(this.description)
);
}
}
This allows you to do the updates like
var newItem = oldItem.With(name: "My name!");
I've used this approach with extension methods and T4s to great effect, but even when you write the code manually, it's reasonably reliable - if you add a new field, you must add it to the With as well, so it works quite well.
There's a few more approaches if you are willing to tolerate runtime code generation and reducing type safety, but that's kind of going against the grain IMO.
With C#9 we got the with operator for this purpose.
public record Car
{
public string Brand { get; init; }
public string Color { get; init; }
}
var car = new Car{ Brand = "BMW", Color = "Red" };
var anotherCar = car with { Brand = "Tesla"};
With-expressions When working with immutable data, a common pattern is
to create new values from existing ones to represent a new state. For
instance, if our person were to change their last name we would
represent it as a new object that’s a copy of the old one, except with
a different last name. This technique is often referred to as
non-destructive mutation. Instead of representing the person over
time, the record represents the person’s state at a given time. To
help with this style of programming, records allow for a new kind of
expression; the with-expression:
News in C#9
NOTE
With operator is only supported by records.
Records At the core of classic object-oriented programming is the idea that an object has strong identity and encapsulates mutable state
that evolves over time. C# has always worked great for that, But
sometimes you want pretty much the exact opposite, and here C#’s
defaults have tended to get in the way, making things very laborious.
Recods in C#9
What you are looking for is commonly called the with operator:
// returns a new immutable object with just the single property changed
someItem = { someItem with Name = "newName" };
Unfortunately, unlike F#, C# does not have such an operator (yet?).
Other C# developers are missing this feature as well, which is why someone wrote a Fody extension to do exactly that:
https://github.com/mikhailshilkov/With.Fody
Here's another approach, which implements an UpdateWith method manually but requires an Option<T> helper class. Luaan's answer describes this approach in more detail:
Implementing F#-inspired "with" updates for immutable classes in C#
Simple solution
I also thought about this question. Record's are not suitable for my purposes, since it is necessary to interact with EF Core.
I suggest a simple and low-cost way:
add a copy constructor to the class;
Make properties that change during cloning available for initialization;
clone an object with a change through the copy constructor with an initialization list:
var a = new SomeItem("name", "abracadabra");
var b = new SomeItem(a) {Description="descr"};
Simple code
var a = new SomeItem("name", "abracadabra");
var b = new SomeItem(a) {Description="descr"};
public class SomeItem
{
private string name;
private string description;
public SomeItem(string name, string description)
{
Name = name;
Description = description;
}
public SomeItem(SomeItem another): this(another.Name, another.Description)
{
}
public string Name
{
get => name;
init => name = value;
}
public string Description
{
get => description;
init => description = value;
}
}
Extended solution
If the final type is not known at compile time, then this approach is easy to extend. Let's say there is a class "ValueObject" whose derived types we need to clone.
Note: I apologize for the incorrect translation in some places. English version obtained using google.translate
Additional code
using System.Linq.Expressions;
using Light.GuardClauses;
using JetBrains.Annotations;
using static DotNext.Linq.Expressions.ExpressionBuilder;
using ValueObject = Company.Domain....;
/// <summary>
/// The plagiarizer creates a copy of the object with a change in its individual properties using an initializer
/// </summary>
/// <remarks> The foreign object must define a copy constructor, and mutable members must support initialization </remarks>
public struct Plagiarist {
/// <summary>
/// Object to be copied
/// </summary>
private readonly object _alienObject;
/// <summary>
/// Type <see cref="_alienObject" />
/// </summary>
private Type _type => _alienObject.GetType();
/// <summary>
/// Object parsing Expression
/// </summary>
private readonly ParsingInitializationExpression _parser = new();
public Plagiarist(object alienObject) {
_alienObject = alienObject.MustNotBeNullReference();
if (!CopyConstructorIs())
throw new ArgumentException($"Type {_type.FullName} must implement a copy constructor");
}
/// <summary>
/// Does the object we want to plagiarize have a copy constructor?
/// </summary>
/// <returns>True - there is a copy constructor, otherwise - false</returns>
[Pure]
private bool CopyConstructorIs() {
return _type.GetConstructor(new[] { _type }) is not null;
}
/// <summary>
/// Returns a copy of a foreign object with a change in its individual properties using an initializer
/// </summary>
/// <param name="initializer">
/// <see cref="Expression" /> create an object with initialization of those fields,
/// which need to be changed:
/// <code>() => new T() {Member1 = "Changed value1", Member2 = "Changed value2"}</code>
/// or <see cref="Expression" /> create an anonymous type with initialization of those fields
/// that need to be changed:
/// <code>() => new {Member1 = "Changed value1", Member2 = "Changed value2"}</code>
/// </param>
/// <returns></returns>
[Pure]
public object Plagiarize(Expression<Func<object>> initializer) {
var (newValues, constructParam) = _parser.ParseInitialization(initializer);
var constrCopies = _type.New(_alienObject.Const().Convert(_type));
Expression plagiarist = (newValues.Count, constructParam.Count) switch {
(> 0, _) => Expression.MemberInit(constrCopies, newValues.Values),
(0, > 0) => Expression.MemberInit(constrCopies, ConstructorInInitializationList(constructParam).Values),
_ => constrCopies
};
var plagiarize = Expression.Lambda<Func<object>>(plagiarist).Compile();
return plagiarize();
}
[Pure]
public Dictionary<string, MemberAssignment> ConstructorInInitializationList(
Dictionary<string, Expression> constructorParameters) {
Dictionary<string, MemberAssignment> initializer = new();
const BindingFlags flagReflections = BindingFlags.Default | BindingFlags.Instance | BindingFlags.Public;
var allProperties = _type.GetProperties(flagReflections);
var allFields = _type.GetFields(flagReflections);
foreach (var memberName in constructorParameters.Keys) {
var property = allProperties.FirstOrDefault(s => s.Name ==memberName);
var field = allFields.FirstOrDefault(s => s.Name == memberName);
(MemberInfo member, Type memberType) = (property, field) switch {
({ }, _) => (property, property.PropertyType),
(null, { }) => ((MemberInfo)field, field.FieldType),
_ => throw new ArgumentException($"{_type.FullName} does not contain member {memberName}")
};
initializer[memberName] = Expression.Bind(member, constructorParameters[memberName].Convert(memberType));
}
return initializer;
}
/// <summary>
/// Template "Visitor" for traversing the expression tree in order to highlight
/// initialization expression and constructor
/// </summary>
private class ParsingInitializationExpression : ExpressionVisitor {
private Dictionary<string, MemberAssignment>? _initializer;
private Dictionary<string, Expression>? _initializerAnonym;
/// <summary>
/// Parses the expression tree and returns the initializer and constructor parameters
/// </summary>
/// <param name="initializer"><see cref="Expression" /> to parse</param>
/// <returns> tuple of initializer and constructor</returns>
public ParsedInitialization ParseInitialization(Expression initializer) {
_initializer = new Dictionary<string, MemberAssignment>();
_initializerAnonym = new Dictionary<string, Expression>();
Visit(initializer);
return new ParsedInitialization(_initializer, _initializerAnonym);
}
protected override MemberAssignment VisitMemberAssignment(MemberAssignment node) {
_initializer![node.Member.Name] = node;
return base.VisitMemberAssignment(node);
}
protected override Expression VisitNew(NewExpression node) {
foreach (var (member, value) in node.Members?.Zip(node.Arguments) ??
Array.Empty<(MemberInfo First, Expression Second)>())
_initializerAnonym![member.Name] = value;
return base.VisitNew(node);
}
/// <summary>
/// Type to return values from method <see cref="ParseInitialization" />
/// </summary>
/// <param name="Initializer"></param>
/// <param name="ConstructorParameters"></param>
public record struct ParsedInitialization(Dictionary<string, MemberAssignment> Initializer,
Dictionary<string, Expression> ConstructorParameters);
}
}
public static class ValueObjectPlagiarizer{
/// <summary>
/// Creates a copy of the object with a change in its individual properties using an initializer
/// </summary>
/// <param name="alien">Object to be plagiarized</param>
/// <param name="initializer">
/// <see cref="Expression" /> creating an object of type <typeparamref name="T" />
/// with initialization of those fields that need to be changed:
/// <code>ob.Plagiarize(() => new T() {Member1 = "Changed value1", Member2 = "Changed value2"})</code>
/// or <see cref="Expression" /> create an anonymous type with initialization of those fields that need to be changed:
/// <code>ob.Plagiarize(() => new {Member1 = "Changed value1", Member2 = "Changed value2"})</code>
/// </param>
/// <returns>plagiarism of the object</returns>
public static object Plagiarize<T>(this ValueObject alien, Expression<Func<T>> initializer)
where T : class {
var bodyReduced = initializer.Convert<object>();
var initializerReduced = Expression.Lambda<Func<object>>(bodyReduced, initializer.Parameters);
return new Plagiarist(alien).Plagiarize(initializerReduced);
}
}
Usages
If SomeItem is a descendant of ValueObject
ValueObject a = new SomeItem("name", "abracadabra");
// via type constructor
var b = (SomeItem)a.Plagiarize(()=>new SomeItem(null){Description="descr"});
// anonymous type
var c = (SomeItem)a.Plagiarize(()=>new{Description="descr"});
b.Description.Should().Be("descr"); //true
c.Description.Should().Be("descr"); //true
If what you want to do is (as you commented) update the name of an existing object, a readonly property might be bad design.
Otherwise if its really a new object you want to create, you might want your class to implement some interface with a 'Dispose' method.
How can we call a function that is defined abstract in a generic base class.
I have a generic
class Class1<T> where T : class, new()
and multiple classes which derive from it like
Class2: Class1<Class2>
Class3: Class1<Class3>
The generic class has 3 functions
1-> accept a dynamic object and puts all the values to corresponding properties in the object of derive
2-> accepts the ID, looks for the corresponding row in database pass the dynamic object to func1 and return the result
3-> a listall function which returns all rows in table
Here is the generic code
public abstract partial class Class1<T> where T : class, new()
{
public static EntityLayout EntityLayout { get; protected set; }
[TypeAttributes(TypeAttributes.Options.IsPrimary, TypeAttributes.Options.IsAutoIncrement)]
/// <summary> Automatically Incremented 64 bit Integer Primary Key
/// represents the Unique ID of each row in Table </summary>
public long ID { get; set; }
/// <summary> Converts the row returned from Database to Object </summary>
/// <param name="row"></param>
/// <returns></returns>
public abstract T GetDetails(dynamic row);
public static T GetDetails(long ID)
{
var row = Shared.SessionWrapper.Current.globaldbcon.QuerySingle("SELECT * FROM ["
+ EntityLayout.ContainerName + "].["
+ EntityLayout.TableName + "] WHERE ID=#0", ID);
if (row != null) return GetDetails(row);
return new T();
}
public static List<T> ListAll()
{
List<T> result = new List<T>();
foreach (var row in Shared.SessionWrapper.Current.globaldbcon.Query("SELECT * FROM ["
+ EntityLayout.ContainerName + "].["
+ EntityLayout.TableName + "]")) result.Add(GetDetails(row));
return result;
}
}
An example class Implementation
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Arinsys.Database;
namespace WebApplication1.Models
{
[EntityAttributes(EntityAttributes.Options.TestingEnabled)]
public class Class3 : Class1<Class3>
{
static Class3()
{
EntityLayout.DisplayName = "Users";
}
/// <summary> User ID of the User </summary>
public long UID { get; set; }
/// <summary> User ID of the User if defined in Universal Data Store </summary>
public long UDSID { get; set; }
/// <summary> Login ID of User </summary>
public string LoginID { get; set; }
/// <summary> Registered email of the user. If not set will be set same as LoginID </summary>
public string Registeredemail { get; set; }
[TypeAttributes(TypeAttributes.Options.IsPassword)]
/// <summary> Password of user </summary>
public string Password { get; set; }
/// <summary> A Unique Security Stamp used for activation/deactivation of account or similar intense tasks </summary>
public string SecurityStamp { get; set; }
/// <summary> Timezone ID of the Default Timezone of User </summary>
public string DefaultTimezone { get; set; }
/// <summary> Current Status of User </summary>
public string CurrentStatus { get; set; }
/// <summary> Discriminator which defines the type of user in multi-user heirarchy scenario </summary>
public string UserType { get; set; }
/// <summary> Number of failed login attempts in total or same session depending upon configuration. Resets after Successful Login </summary>
public short FailedAttempts { get; set; }
/// <summary> Date Time of Last Failed Login Attempt in UTC </summary>
public DateTime LastFailedAttempt { get; set; }
/// <summary> Date Time of Last Successful Login in UTC </summary>
public DateTime LastLogin { get; set; }
/// <summary> Creation Date of User Account in UTC </summary>
public DateTime CreationDate { get; set; }
public override Class3 GetDetails(dynamic row)
{
Class3 result = new Class3();
if (row != null)
{
result.ID = Convert.ToInt64(row.ID);
result.UID = Convert.ToInt64(row.UID);
result.UDSID = Convert.ToInt64(row.UDSID);
result.UserType = row.UserType;
result.LoginID = row.LoginID;
result.Password = row.Password;
result.Registeredemail = row.Registeredemail;
result.SecurityStamp = row.SecurityStamp;
result.DefaultTimezone = row.DefaultTimezone;
result.CurrentStatus = row.CurrentStatus;
result.FailedAttempts = Convert.ToInt16(row.FailedAttempts);
result.LastFailedAttempt = Convert.ToDateTime(row.LastFailedAttempt);
result.LastLogin = Convert.ToDateTime(row.LastLogin);
result.CreationDate = Convert.ToDateTime(row.CreationDate);
}
return result;
}
}
}
Its been two weeks searching for the answer everywhere before posting, but couldn't find the solution.
All i want is that ListAll function should call 1st function. Since it's defined abstract i am sure the deriving class has to have an implementation (even though it might be just throw NotImplementException, but implementation is guaranteed)
I first defined the implementation of 1st function in generic class itself through reflection. Though that works, but its very slow, did performance bench-marking by starting/stopping a Stopwatch at start/end of controller action and it took approx 35 seconds for just 100 rows, so it's surely not something for production use.
Points to note
Static cannot be defined abstract
Cannot access instance member from static context
Cant use reflection because of performance issues
Possible Solutions i guess are closest ( but i am unable to understand how to use them in my case)
convert all methods to instance methods and use singleton
using interfaces
define a static method in derived class and assume it will be there in all classes, if i go this way then how to access static method on T in that case
What i want to achieve is that ListAll function should call 1st function accepting a dynamic object.
Some questions which come very close are these, but none of them solves my query.
Stack Overflow Q1 Stack Overflow Q2 Stack Overflow Q3
Looks like the design should be like this
public abstract partial class Class1<T> where T : Class1<T>, new()
{
protected abstract void Load(dynamic row);
private static T GetItem(dynamic row)
{
var item = new T();
if (row != null)
item.Load(row);
return item;
}
public static T GetDetails(long ID)
{
var row = Shared.SessionWrapper.Current.globaldbcon.QuerySingle("SELECT * FROM ["
+ EntityLayout.ContainerName + "].["
+ EntityLayout.TableName + "] WHERE ID=#0", ID);
return GetItem(row);
}
public static List<T> ListAll()
{
List<T> result = new List<T>();
foreach (var row in Shared.SessionWrapper.Current.globaldbcon.Query("SELECT * FROM ["
+ EntityLayout.ContainerName + "].["
+ EntityLayout.TableName + "]")) result.Add(GetItem(row));
return result;
}
}
and the sample implementation
public class Class3 : Class1<Class3> {
{
// ...
protected override void Load(dynamic row)
{
// No need to check for null, it is enforced by the base class
ID = Convert.ToInt64(row.ID);
UID = Convert.ToInt64(row.UID);
// ...
}
}
Basically you explore the Curiously recurring template pattern supported by .NET generic class constraints (T : Class1<T>) to ensure the derived class contains the abstract Load method, while the new T() part is enforced by the new() constraint.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
If I have a class which represent a mapping to a specific table in my db in somehow.
This class contains about 30 properties.
I have created the CRUD Methods.
And find myself need to another (UPDATE) method which should update just two fields.
What should I do in a good manner with simple example?
Using my exist method, Filling the whole object and update all the fields including my intended two fields? (Useless work)
Create static Method with another name (but I want to keep my method name because it's expressive)! And takes two parameters?
I would go by by creating two separate interface and create overloaded functions for each interface. I would group properties based on usage, like I want status to be updated some time separate from other common properties.
public interface ICommonProperties
{
public string P1{get; set;}
public string P2{get; set;}
public string P3{ get; set; }
}
public interface ITrackable
{
public string Status{get; set;}
}
public class FinalClass : ICommonProperties, ITrackable
{
public string P1{get; set;}
public string P2{get; set;}
public string P3{get; set;}
public string Status{get; set;}
}
public class FinalClassOperations
{
public void Update(FinalClass finalClassInstance) { }; //Updates everything
public void Update(ICommonProperties finalClassInstance) { }; //Updates only ICommonProperties
public void Update(ITrackable finalClassInstance) { }; //updates only Status.
}
Additionally, if you want you can create a separate class for just updating the status, and that would still fit in:
public class Tracker : ITrackable{
public string Status{get; set;}
}
But yes, if the two properties cannot be separated out logically, I would not do that and keep them together.
I would suggest to follow your second option but there is no need to change the name as the number of method parameter will be different on both it's
Let's as walk into few example
I will try to create an similar situation, I hope it's your situation. you can clarify if i got wrongly the question.
CLASSES AND METHOD
/// <summary>
/// CLass to store properties related to database
/// </summary>
class ObjectoA
{
public string A{get; set;}
public string B{get; set;}
public string C{ get; set; }
}
/// <summary>
/// class to call method to update.
///
/// </summary>
class ObjectB
{
/// <summary>
/// update method.
/// I would go with this solution.
/// optionlay you can call the method which receive parameter of object
/// </summary>
/// <param name="A"> Object with properties mapped to database</param>
/// <param name="updatetwoproperties">Optional paramneter to decide which update to run.
/// the default value should be for update that run most. For your need if you want to create an update methods for other
/// two sets of parameter a suggest you create an Enum and pass this enum as optional parameter instead of bool parameter or you
/// can pass as string and map each string value to specific update inside. IF YOU NEED EXAMPLE
/// REPLAY ON COMMENTS</param>
/// <returns></returns>
public bool update(ObjectoA A, bool updatetwoproperties=false)
{
//method implementation
if (updatetwoproperties)
{
//implement a update to all field
}
else
{
//implement update just to two field
}
return true;
}
/// <summary>
/// update method based on parameter to update
/// </summary>
/// <param name="a">this properties is mapped on database</param>
/// <param name="b">this propertie is mapped on database</param>
/// <returns></returns>
public bool update(string a, string b)
{
//method implementation e validate the return value
return true;
}
}
/// <summary>
/// I don't suggest to use this solution because
/// it will add a method on string type while this method isn't related to string
/// I just added here as a workaround for you.
/// </summary>
public static class ObjectC
{
public static bool update(this string a, string b)
{
//implementation of update and validate the return value
return true;
}
}
CALLING METHOD AND EXPLANATION
static void Main(string[] args)
{
ObjectB B = new ObjectB(); //Class with methods
ObjectoA A = new ObjectoA(); //object with properties
#region Using Optional parameter to decide which update to run
//Calling a method to update all columns
B.update(A);
//Calling a method to update two columns
B.update(A, true);
#endregion
#region Using polymorphism to update
//Calling a method to update all columns
B.update(A);
//Update only using paramenter
B.update(A.B, A.C);
#endregion
//NOT RECOMMEND BECAUSE THIS UPDATE ISN'T RELATED TO STRING TYPE
#region Using extension method to update
//Calling a method to update all columns
B.update(A);
//using the extension method on variable type
A.B.update(A.C);
#endregion
//WE COULD USE EXTENSION METHOD ON YOUR OBJECT BUT IT WILL FAIL BECAUSE WE ALREADY AS UPDATE METHOD ON CLASS
//IF YOU WANT TO SEE HOW JUST REPLAY
}
I SUGGEST YOU ADD OPTIONAL PARAMETER ON YOUR METHOD TO DECIDE WHICH UPDATE TO USE
It depends on what your priorities are on the project:
using your already existing update method is gonna update everything all the time, incressing traffic, IO and process time (validation and so on...)
If you're on a project where properties are timestamped, they would be updated even if the value hasn't really changed...
If you don't mind about all this, use your update() method all the time.
My personnal POV is: create a new method (with an explicit name). This will same process time from now on and thinking time in 2 years when you'll have to change this class ;)
I don't know if this is what you should do necessarily, but here's something you could do: Create a SetAll or SetMany or whatever method where you pass in another instance of your class (source). Check each property and if it's non-null, you set the destination object's property value to the source object's property value. Note that this tactic will depend on nullable types, and assumes you can ignore null values passed into a new setter method. Here's an illustration:
using System;
namespace BlogPartialUpdateTrick
{
public class SomeClass
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int? HeightInches { get; set; }
public DateTime? Dob { get; set; }
public void SetAll(SomeClass source)
{
this.FirstName = source.FirstName ?? this.FirstName;
this.LastName = source.LastName ?? this.LastName;
this.HeightInches = source.HeightInches ?? this.HeightInches;
this.Dob = source.Dob ?? this.Dob;
}
public override string ToString()
{
return String.Format("fn: {0}, ln: {1}, height: {2}, DOB: {3}", FirstName ?? String.Empty, LastName ?? String.Empty,
HeightInches.HasValue ? HeightInches.Value.ToString() : "null", Dob.HasValue ? Dob.Value.ToShortDateString() : "null" );
}
}
}
In this first code sample, We have my spiffy class SomeClass. It's got 4 properties, all of which are nullable. The noteworthy part of this class is the SetAllMethod where I can pass in a source object which is also of type SomeClass. It sets this instance's property values to the values passed in the source parameter, but only if they're non-null. Here's a 2nd code blurb where I'm using this stuff:
using System;
using System.Windows.Forms;
namespace BlogPartialUpdateTrick
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var destination = new SomeClass() { FirstName = "Freddy", LastName = "Fingers", Dob = DateTime.Parse("01/01/1970"), HeightInches = 72 };
var source = new SomeClass() { FirstName = null, LastName="Flippers", Dob = null, HeightInches = 80 };
destination.SetAll(source);
MessageBox.Show(destination.ToString());
}
}
}
Create a destination object, a source object, call the new method, voila! output is this:
"fn: Freddy, ln: Flippers, height: 80, DOB: 1/1/1970"
You should probably use Entity Framework and let the context do it for you. Using EF, you'll be able to update Entities like this :
try
{
var original = ObjectContext.Set<Request>().SingleOrDefault(x => x.Id.Equals(_request.Id));
if (original != null)
{
ObjectContext.Entry(original).CurrentValues.SetValues(_request);
}
return ObjectContext.SaveChanges();
}
catch (Exception ee)
{
return -1;
}
Maybe the title is not good enough, I know. Here is my propblem.
I'm currently writing a class library for a program which handles the new version checks and downloads of the patches.
A dedicated updating framework is no option for me because they mostly are too bloated. I really only want to query the server, check for a new version and if there is a new version download the patch.
In my current setup I have a class which calls the server that returns a json encoded text document (for now, we are going to switch toWebApi2 later). This text document is then deserialized by JSON.NET into a list of the following c# object.
/// <summary>Represents a patch.</summary>
/// ToDo: Implement ICompareable and IEquatable
public class Patch
{
/// <summary>Initializes a new instance of the <see cref="Patch"/> class.</summary>
/// <param name="version">The version of the patch.</param>
[JsonConstructor]
public Patch(string version)
: this(new Version(version))
{
}
/// <summary>Initializes a new instance of the <see cref="Patch"/> class.</summary>
/// <param name="version">The version of the patch as string.</param>
public Patch(Version version)
{
this.Version = version;
}
/// <summary>Gets the version of the patch.</summary>
[JsonConverter(typeof(VersionConverter))]
public Version Version { get; private set; }
/// <summary>Gets or sets the size of the patch.</summary>
public long Length { get; set; }
/// <summary>Gets or sets the primary download uri.</summary>
public Uri DownloadUri { get; set; }
/// <summary>Gets or sets the fallback download uri.</summary>
public Uri FallbackUri { get; set; }
}
After deserialization I iterate through said list and check if a new version is available. If there is a new version available the method returns with true. If there is no new version available the method returns with false.
Now I'm puzzled what is the best way to return the version object itself. I could do this with an out parameter, but I'm not sure if this is the best way. Especially since the checking method has to rerun until it returns false (meaning the program is at the latest version).
Could events be a possibility? How about a tuple? Or am I missing something completely?
//edit: For those who are interested, here is the method which I'm talking about.
public bool CheckForNewVersion(out Patch newPatch)
{
string versionFileContents = this.GetVersionFile();
List<Patch> patches = this.Deserialize(versionFileContents);
foreach (Patch patch in patches)
{
if (patch.Version > this.CurrentVersion)
{
newPatch = patch;
return true;
}
}
newPatch = null;
return false;
}
You could change the signature of the method to something like this
public IEnumerable<Patch> GetUpdates(string currentClientVersion)
{
var updates = new List<Patch>();
if (currentClientVersion != LatestVersion)
{
updates = GetRequiredUpdates(currentClientVersion);
}
return updates;
}
This would give you a list of all the updates to apply, or an empty list if the client has the latest version installed.
Unless i'm misinterpreting the question, I would prefer objects to encapsulate the data required and returned. This will allow you to add any new functionality in the future (as this is an API).
//What patches are available?
public class PatchCheckOutcome {
public PatchCheckOutcome(bool newPatchAvailble, List<Patch> availablePatches) {
NewPatchAvailable = newPatchAvailable;
AvailablePatches = availablePatches ?? New List<Patch>();
}
public bool NewPatchAvailable { get; private set; }
public List<Patch> AvailablePatches { get; private set; }
}
//Information required to check what patches are available
public class PatchCheckInformation {
public string CurrentVersion { get; set; }
}
//API method
public PatchCheckOutcome GetAvailablePatches(PatchCheckInformation info);