DapperLib / Dapper

Dapper - a simple object mapper for .Net
https://www.learndapper.com/
Other
17.3k stars 3.67k forks source link

@UniqueID error #2024

Open berets76 opened 6 months ago

berets76 commented 6 months ago

Hi, I've a table with a field named UniqueID, but when I try to insert or update through Dapper I get an error on the variable name

image

It seems like it's some kind of reserved word/variable name. I'm using Dapper version 2.1.28 with Microsoft SQL Azure

I tried to escape it with [] but no way. The @UniqueID variable is present only one time. If I remove the UniqueID field and variable from queries, all works fine.

These are my query:

`internal static readonly string INSERT_QUERY = "INSERT INTO pro_ordine_composizione (SocietaID,OrdineID,ArticoloID,RevisioneID,ComposizioneID,LogAdded,LogUpdated,LogCanceled,LogAddedUserID,LogUpdatedUserID,LogCanceledUserID,ComponenteArticoloID,ComponenteRevisioneID,ComposizioneIDPadre,RepartoID,ComponenteID,Posizione,Quantita,Tempo,Inizio,Fine,RisorsaID,ESummary,EMilestone,DescrizioneMS,UniqueID,EFisso,TempoAlPezzo,Note,Piazzamento,UID,QuantitaOriginale) OUTPUT INSERTED.rv VALUES(@SocietaID,@OrdineID,@ArticoloID,@RevisioneID,@ComposizioneID,SYSUTCDATETIME() AT TIME ZONE 'UTC' AT TIME ZONE 'Central Europe Standard Time',@LogUpdated,@LogCanceled,@LogAddedUserID,@LogUpdatedUserID,@LogCanceledUserID,@ComponenteArticoloID,@ComponenteRevisioneID,@ComposizioneIDPadre,@RepartoID,@ComponenteID,@Posizione,@Quantita,@Tempo,@Inizio,@Fine,@RisorsaID,@ESummary,@EMilestone,@DescrizioneMS,@UniqueID,@EFisso,@TempoAlPezzo,@Note,@Piazzamento,@UID,@QuantitaOriginale)";

internal static readonly string UPDATE_QUERY = "UPDATE pro_ordine_composizione SET SocietaID = @SocietaID,OrdineID = @OrdineID,ArticoloID = @ArticoloID,RevisioneID = @RevisioneID,ComposizioneID = @ComposizioneID,LogAdded = @LogAdded,LogUpdated = SYSUTCDATETIME() AT TIME ZONE 'UTC' AT TIME ZONE 'Central Europe Standard Time',LogCanceled = @LogCanceled,LogAddedUserID = @LogAddedUserID,LogUpdatedUserID = @LogUpdatedUserID,LogCanceledUserID = @LogCanceledUserID,ComponenteArticoloID = @ComponenteArticoloID,ComponenteRevisioneID = @ComponenteRevisioneID,ComposizioneIDPadre = @ComposizioneIDPadre,RepartoID = @RepartoID,ComponenteID = @ComponenteID,Posizione = @Posizione,Quantita = @Quantita,Tempo = @Tempo,Inizio = @Inizio,Fine = @Fine,RisorsaID = @RisorsaID,ESummary = @ESummary,EMilestone = @EMilestone,DescrizioneMS = @DescrizioneMS,UniqueID = @UniqueID,EFisso = @EFisso,TempoAlPezzo = @TempoAlPezzo,Note = @Note,Piazzamento = @Piazzamento,[UID] = @UID,QuantitaOriginale = @QuantitaOriginale OUTPUT INSERTED.rv WHERE SocietaID = @SocietaID AND OrdineID = @OrdineID AND ArticoloID = @ArticoloID AND RevisioneID = @RevisioneID AND ComposizioneID = @ComposizioneID AND rv = @rv";`

Regards

mgravell commented 6 months ago

Can we see how you're invoking the SQL? Including (and in particular) the parameters? I can't do much without seeing the usage.

mgravell commented 6 months ago

I wonder, in particular, whether you somehow have a @uniqueId and @UniqueId (or similar), leading to this.

mgravell commented 6 months ago

In this example, Model is what defined the parameters. So: can we see the type that describes Model ? In particular, anything even remotely relating to unique id - regardless of kind (property, field, etc) or accessibility (public, private, etc)

berets76 commented 6 months ago

Sorry I accidentally deleted previous comment.

Basically

using IDbConnection connection = new ConnectionFactory().CreateSQL();

if (connection != null)
{
    connection.Open();
    var result = connection.ExecuteScalar(UPDATE_QUERY, Model);

Model is the class with UniqueID field

Checking the Model class maybe I found the problem: my partial class has this signature public partial class pro_ordine_composizione : GanttTask, INotifyPropertyChanged

in the Telerik.Windows.Controls.GanttView.GanttTask there is another uniqueid property.

So, I've my base class

public partial class pro_ordine_composizione 
{

    private string? _UniqueID;
    public string? UniqueID { get => _UniqueID; set { if (_UniqueID != value) { _UniqueID = value; OnPropertyChanged();} } }

my partial (with non relevant things)

public partial class pro_ordine_composizione : GanttTask, INotifyPropertyChanged

and finally the GanttTask

[Serializable]
public class GanttTask : PropertyChangedBase, IGanttTask, IDateRange, IResourceContainer, IHierarchical, IStateProvider, IMilestone, ISummary, IEditableHierarchical, IDependant
{
    private ObservableCollection<IResource> resources;

    private DateTime start;

    private DateTime end;

    private string title = string.Empty;

    private string description = string.Empty;

    private double progress;

    private DateTime? deadLine;

    private bool isExpired;

    private bool isExpiredUpdate = true;

    private bool isMilestone;

    private string uniqueId;

Maybe is this the problem ? But Dapper how deep goes to add parameters ?

mgravell commented 6 months ago

All the deep. There are some ways of configuring this, but honestly: in most cases it is more pragmatic just to:

new { obj.Foo, obj.Bar, obj.Blap }

to explicitly call out the things you want.

This is an interesting scenario, though. I wonder whether we could do something over in AOT-land to specify better restriction rules (in the AOT work, we have much better analysis tooling, and better ways of specifying configuration)

berets76 commented 6 months ago

I've already tested AOT with a part of our software (with good results), when do you think it might be "safe" to switch prod environment to AOT ?

mgravell commented 6 months ago

I'm going to refer to the Apache license to answer that:

Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.

If it works, great! I feel comfortable using it, as long as I have integration tests working.